package cn.roadtrip.mtravelbusinessmodule.bs.tuorgroup;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.DesensitizedUtil;
import cn.hutool.core.util.IdcardUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.digest.MD5;
import cn.roadtrip.mtravelbusinessmodule.bs.basic.BasicBusinessImpl;
import cn.roadtrip.mtravelbusinessmodule.sql.couple.dto.BsUserLayoutUserInforDTO;
import cn.roadtrip.mtravelbusinessmodule.sql.couple.dto.CoupleShopPdtDTO;
import cn.roadtrip.mtravelbusinessmodule.sql.couple.tables.records.CoupleShopPdtRecord;
import cn.roadtrip.mtravelbusinessmodule.sql.couple.tables.records.CoupleUserDiscountCouponRecord;
import cn.roadtrip.mtravelbusinessmodule.sql.couple.travelgroup.dto.BsMyContactPeopleDTO;
import cn.roadtrip.mtravelbusinessmodule.sql.couple.travelgroup.dto.BsTravelGroupCreatorSayDTO;
import cn.roadtrip.mtravelbusinessmodule.sql.couple.travelgroup.dto.BsTravelGroupMainTuorTravelLineRecordDTO;
import cn.roadtrip.mtravelbusinessmodule.sql.couple.travelgroup.tables.records.*;
import cn.roadtrip.mtravelbusinessmodule.sql.couple.travelline.dto.BsHotelRoomPriceDTO;
import cn.roadtrip.mtravelbusinessmodule.sql.couple.travelline.dto.BsInsuranceDataDTO;
import cn.roadtrip.mtravelbusinessmodule.sql.couple.travelline.dto.BsPreTravelCarPriceDTO;
import cn.roadtrip.mtravelbusinessmodule.sql.couple.travelline.dto.BsTravelLinePlatPreTravelLineDTO;
import cn.roadtrip.mtravelbusinessmodule.sql.couple.travelline.tables.BsThirdinsurancelog;
import cn.roadtrip.mtravelbusinessmodule.sql.couple.travelline.tables.records.BsMycontactpeopleRecord;
import cn.roadtrip.mtravelbusinessmodule.sql.couple.travelline.tables.records.BsThirdinsurancelogRecord;
import cn.roadtrip.mtravelbusinessmodule.sql.couple.travelline.tables.records.BsTravellinePlatpretravellineRecord;
import cn.roadtrip.mtravelbusinessmodule.util.api.ins.InsuranceImpl;
import cn.roadtrip.mtravelbusinessmodule.util.api.ins.model.InsData;
import cn.roadtrip.mtravelbusinessmodule.util.api.ins.model.InsuredInfo;
import cn.roadtrip.mtravelbusinessmodule.util.api.ins.model.OrderInfo;
import cn.roadtrip.mtravelbusinessmodule.util.api.ins.model.PolicyHolderInfo;
import cn.roadtrip.utilmodule.util.DataBean;
import cn.roadtrip.utilmodule.util.enumpck.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.github.yitter.idgen.YitIdHelper;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import lombok.*;
import lombok.extern.slf4j.Slf4j;
import org.jooq.DSLContext;
import org.jooq.impl.DSL;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.*;
import java.util.concurrent.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static cn.roadtrip.mtravelbusinessmodule.sql.couple.Tables.BS_USERLAYOUT_USERINFOR;
import static cn.roadtrip.mtravelbusinessmodule.sql.couple.tables.CoupleComment.COUPLE_COMMENT;
import static cn.roadtrip.mtravelbusinessmodule.sql.couple.tables.CoupleShopPdt.COUPLE_SHOP_PDT;
import static cn.roadtrip.mtravelbusinessmodule.sql.couple.tables.CoupleUserDiscountCoupon.COUPLE_USER_DISCOUNT_COUPON;
import static cn.roadtrip.mtravelbusinessmodule.sql.couple.travelgroup.Tables.*;
import static cn.roadtrip.mtravelbusinessmodule.sql.couple.travelline.tables.BsHotelroomprice.BS_HOTELROOMPRICE;
import static cn.roadtrip.mtravelbusinessmodule.sql.couple.travelline.tables.BsInsurancedata.BS_INSURANCEDATA;
import static cn.roadtrip.mtravelbusinessmodule.sql.couple.travelline.tables.BsMycontactpeople.BS_MYCONTACTPEOPLE;
import static cn.roadtrip.mtravelbusinessmodule.sql.couple.travelline.tables.BsPretravelcarprice.BS_PRETRAVELCARPRICE;
import static cn.roadtrip.mtravelbusinessmodule.sql.couple.travelline.tables.BsTravellinePlatpretravelline.BS_TRAVELLINE_PLATPRETRAVELLINE;
import static cn.roadtrip.utilmodule.util.DataBean.err;
import static cn.roadtrip.utilmodule.util.DataBean.suc;

/**
 * 用户旅游操作
 */
@Component
@Slf4j
public class TourTravelImpl {

    @Autowired
    private DSLContext dslContext;
    @Autowired
    private InsuranceImpl insuranceImpl;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private BasicBusinessImpl basicBusinessImpl;

    @Autowired
    private RedissonClient redissonClient;//分布式锁

    //上锁，避免报名人数超出
    public static final String TOUR_TRAVELLINE_ORDER_LOCK = "createPreTuorTravelLineOrder";

    /**
     * 用户报团检查-redis
     */
    public static final String USER_JOIN_TOURTRAVELLINE_PREFIX = "user-join-tourtravelline:";
    /**
     * 预付款报团费用记录-redis
     */
    public static final String USER_JOIN_TOURTRAVELLINE_PRICELIST_PREFIX = "user-join-tourtravelline-pricelist:";

    /**
     * 游客创建的缓存
     */
//    public static final String TOUR_TRAVELGROUP_DETAIL_PREFIX = "tourTravelDetail:";

    //查询业务的任务线程
    private ExecutorService queryService;

    @PostConstruct
    public void init() {
        queryService = Executors.newFixedThreadPool(12);
    }

    @PreDestroy
    public void destroy() {
        queryService.shutdown();
    }

    /**
     * 订单操作记录
     */
    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    @EqualsAndHashCode
    public static class TOUR_TRAVELORDER_CTL {
        private Enum_TravelGroupTourOrderStats stats;
        private Long createTime;
        private java.util.Map<String, Object> dataMap;

    }

    /**
     * 每日行程
     */
    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    @EqualsAndHashCode
    public static class _TravelLine_DayScenic_ {
        private String scenicId;
        private Integer sortOrder;
        private Integer dayNum;//第几天
        private String scenicTitle;
        private String playTime;//玩多久
    }


    /**
     * 检查用户是否可以创建团
     *
     * @param userId    用户ID
     * @param startDate 开始日期
     * @param playDays  游玩天数
     * @return
     */
    public boolean _checkCanCreateTourTravelLine(String userId, Long startDate, Integer playDays) {
        BsTravelgroupMaintuortravellinerecordRecord record = dslContext.selectFrom(BS_TRAVELGROUP_MAINTUORTRAVELLINERECORD).where(BS_TRAVELGROUP_MAINTUORTRAVELLINERECORD.CREATEUSERID.eq(userId).and(BS_TRAVELGROUP_MAINTUORTRAVELLINERECORD.STATS.in(Enum_MainTourTravelLineStats.WaitOwner.getCode(), Enum_MainTourTravelLineStats.Freze.getCode(), Enum_MainTourTravelLineStats.Wait.getCode(), Enum_MainTourTravelLineStats.ApplyOk.getCode(), Enum_MainTourTravelLineStats.ApplyOk.getCode())).and(BS_TRAVELGROUP_MAINTUORTRAVELLINERECORD.STARTDATE.lessOrEqual(startDate + (playDays - 1) * DateUnit.DAY.getMillis())).and(BS_TRAVELGROUP_MAINTUORTRAVELLINERECORD.STARTDATE.greaterOrEqual(startDate))).limit(1).fetchOne();
        if (record == null) return true;
        return record.getCreateuserid().equals(userId);
    }


    /**
     * 释放用户抱团的锁定
     *
     * @param travelGroupId
     * @param userId
     * @param startDate
     * @param playDays
     * @return
     */
    public String _unlockJoinTourTravelLine(String travelGroupId, String userId, String startDate, Integer playDays) {
        String key = USER_JOIN_TOURTRAVELLINE_PREFIX + userId;
        Long len = redisTemplate.opsForList().size(key);
        if (len == null || len.longValue() == 0) {
            return null;
        }
        long startdate = DateUtil.parseDate(startDate).getTime();
        long enddate = startdate + (playDays - 1) * DateUnit.DAY.getMillis();
        String v = startdate + ":" + enddate + ":" + travelGroupId;
        Long i = redisTemplate.opsForList().remove(USER_JOIN_TOURTRAVELLINE_PREFIX + userId, 0, v);
        return (i == null || i.longValue() == 0) ? null : v;
    }

    /**
     * 锁定用户已抱团
     *
     * @param travelGroupId
     * @param userId
     * @param startDate
     * @param playDays
     * @return
     */
    public String _lockJoinTourTravelLine(String travelGroupId, String userId, String startDate, Integer playDays) {
        java.util.List<String> list = redisTemplate.opsForList().range(USER_JOIN_TOURTRAVELLINE_PREFIX + userId, 0, -100);
        if (list == null) list = new ArrayList<>();
        String key = USER_JOIN_TOURTRAVELLINE_PREFIX + userId;
        Long len = redisTemplate.opsForList().size(key);
        long startdate = DateUtil.parseDate(startDate).getTime();
        long enddate = startdate + (playDays - 1) * DateUnit.DAY.getMillis();
        String v = startdate + ":" + enddate + ":" + travelGroupId;
        for (String s : list) {
            if (s.equals(v)) {
                return s;
            }
        }
        redisTemplate.opsForList().rightPush(key, v);
        return v;
    }

    /**
     * 检查是否已经抱团了
     *
     * @param userId
     * @return
     */
    public String _hasJoinTourTravelLine(String userId, String startDate, Integer playDays) {
        java.util.List<String> list = redisTemplate.opsForList().range(USER_JOIN_TOURTRAVELLINE_PREFIX + userId, 0, -1);
        if (list == null || list.isEmpty()) {
            return null;
        }
        //保存的值：开始日期[时间戳]:结束日期[时间戳]:[BS_TravelGroup_MainTuorTravelLineRecord.Id]
        long startdate = DateUtil.parseDate(startDate).getTime();
        long enddate = startdate + (playDays - 1) * DateUnit.DAY.getMillis();
        for (String s : list) {
            String[] ds = s.split(":");
            long sd = Long.parseLong(ds[0]);
            long ed = Long.parseLong(ds[1]);
            if (sd <= startdate && startdate <= ed) {
                return s;
            }
            if (sd <= enddate && enddate <= ed) {
                return s;
            }
        }
        return null;
    }

    /**
     * 获取预置路线所属租户ID
     *
     * @param preTravelLineId
     * @return
     */
    public BsTravellinePlatpretravellineRecord _getPreTravelLineById(String preTravelLineId) {
        return dslContext.selectFrom(BS_TRAVELLINE_PLATPRETRAVELLINE).where(BS_TRAVELLINE_PLATPRETRAVELLINE.TRASH.eq(false).and(BS_TRAVELLINE_PLATPRETRAVELLINE.ID.eq(preTravelLineId))).fetchOne();
    }


    /**
     * 查询游玩天数相对应得房间价格--最小
     *
     * @param days
     * @return
     */
    public BigDecimal _getPreHotelRoomPriceByDays_Min(Integer days) {
        BigDecimal r = dslContext.select(BS_HOTELROOMPRICE.PRICE).from(BS_HOTELROOMPRICE).where(BS_HOTELROOMPRICE.TRASH.eq(false)).and(BS_HOTELROOMPRICE.DAYNUM.eq(days)).orderBy(BS_HOTELROOMPRICE.PRICE.asc()).limit(1).fetchOneInto(BigDecimal.class);
        return r;
    }

    /**
     * 查询游玩天数相对应得车价格--最小
     *
     * @param days
     * @return
     */
    public BigDecimal _getPreCarPriceByDays_Min(Integer days) {
        BigDecimal r = dslContext.select(BS_PRETRAVELCARPRICE).from(BS_PRETRAVELCARPRICE).where(BS_PRETRAVELCARPRICE.TRASH.eq(false)).and(BS_PRETRAVELCARPRICE.DAYNUM.eq(days)).orderBy(BS_PRETRAVELCARPRICE.PRICE.asc()).limit(1).fetchOneInto(BigDecimal.class);
        return r;
    }

    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    @EqualsAndHashCode
    public static class Model_createTuorGroup {
        private String startFromCityId;//出发城市ID
        private String startFromCityTitle;//出发城市名
        private String createUserId;//创建者ID
        private String preTravelLineId;//旅游路线ID
        private String startDate;//开始日期
        private Integer travelDays;//旅游天数
        private Integer maxUserNum;//最大人数
        private java.util.Map<String, Object> extInfor;//其他信息
        private java.util.List<Object> preTravelCarList;//选择车辆
        //        private java.util.List<_TravelLine_DayScenic_> dayScenicList;//每日景点
        private Object dayScenicList;//每日景点
        private Enum_TourTravelGroupType groupType;//团类型
    }

    /**
     * 01 创建人创建团
     */
    public DataBean createTuorTravelLineGroup(Model_createTuorGroup model) {
        if (model.getGroupType() == null) {
            model.setGroupType(Enum_TourTravelGroupType.Self);
        }
        //验证owner是否已经创建过有效团
        boolean canCreate = _checkCanCreateTourTravelLine(model.getCreateUserId(), DateUtil.parseDate(model.getStartDate()).getTime(), model.getTravelDays());
        if (!canCreate) {
            return err("cant-create", "期间你已经创建过团，无法再创建");
        }
        //检查是否已经抱团
        String turTravelLineId = _hasJoinTourTravelLine(model.getCreateUserId(), model.getStartDate(), model.getTravelDays());
        if (turTravelLineId != null) {
            return err("already-join", "你已经参与了旅游团");
        }
        Long startDate = DateUtil.parseDate(model.getStartDate()).getTime();
        Long today = DateUtil.parseDate(DateUtil.today()).getTime();
        if ((today + DateUnit.DAY.getMillis()) > startDate) {
            return err("cant-create", "行程开始时间至少需要提前2天");
        }
        if (model.getTravelDays() <= 0) {
            return err("playdays-err", "游玩时间太少");
        }
        //创建团
        BsTravellinePlatpretravellineRecord preTravelLine = _getPreTravelLineById(model.getPreTravelLineId());
        if (preTravelLine == null) {
            return err("travelline-err", "路线信息异常");
        }

        //查询车价
        BigDecimal carPrice = _getPreCarPriceByDays_Min(model.getTravelDays());
        if (carPrice == null) {
            carPrice = new BigDecimal(0);
        }
        if (model.getExtInfor() == null) {
            model.setExtInfor(new HashMap<>());
        }
        //将车价作为起步价
        {
            model.getExtInfor().put("globStartPrice", carPrice.toString());
        }

        try {
            return dslContext.transactionResult(ctx -> {
                Gson gson = new Gson();
                String id = "" + YitIdHelper.nextId();
                int cout = dslContext.insertInto(BS_TRAVELGROUP_MAINTUORTRAVELLINERECORD).set(new BsTravelgroupMaintuortravellinerecordRecord(id, model.getGroupType().getCode(), Enum_MainTourTravelLineStats.WaitOwner.getCode(), Enum_MainTourTravelLineDispatchStats.Audit.getCode(), model.getCreateUserId(), model.getPreTravelLineId(), preTravelLine.getTenantid(), startDate, model.getTravelDays(), model.getMaxUserNum(), "0", model.getStartFromCityId(), "0", preTravelLine.getContractid(), preTravelLine.getInsuranceid(), startDate - DateUnit.HOUR.getMillis() * 12, System.currentTimeMillis(), model.getStartFromCityTitle(), preTravelLine.getPrelinename(), "", gson.toJson(model.getExtInfor()), gson.toJson(model.getPreTravelCarList()), gson.toJson(model.getDayScenicList()))).execute();
                dslContext.commit();
                if (cout == 0) {
                    return err("err", "创建失败");
                }
                //新增出发城市
                dslContext.insertInto(BS_TRAVELGROUP_STARTFROMCITY).set(new BsTravelgroupStartfromcityRecord(YitIdHelper.nextId() + "", false, id, model.getStartFromCityId(), "")).execute();
                return suc(id, 1, "suc", "操作成功");
            });
        } catch (Exception e) {
            e.printStackTrace();
            return err("trans-err", e.getMessage());
        }
    }

    /**
     * 01-01 提供预算费用
     */
    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    @EqualsAndHashCode
    public static class Model_provideTuorTravelLineOrderBudget {
        private String userId;
        private String tuorTravelGroupId;//团行程ID
        private String ticketId;//优惠券ID,可选
    }

    /**
     * 检查票据是否可用
     *
     * @param ticketId
     * @param userId
     * @return
     */
    private CoupleUserDiscountCouponRecord _checkTicket(String ticketId, String userId) {
        return dslContext.selectFrom(COUPLE_USER_DISCOUNT_COUPON).where(COUPLE_USER_DISCOUNT_COUPON.ID.eq(ticketId)).fetchOne();
    }

    /**
     * 预算费用  -- 报名第一步的操作
     *
     * @param model
     * @return
     */
    public DataBean provideTuorTravelLineOrderBudget(Model_provideTuorTravelLineOrderBudget model) {
        //判断优惠券
        CoupleUserDiscountCouponRecord ticket = null;
        if (model.getTicketId() != null) {
            //验证优惠券
            ticket = _checkTicket(model.getTicketId(), model.getUserId());
            if (ticket == null) {
                return err("ticket-err", "优惠券不存在");
            }
            if (ticket.getExpirationTime().toInstant(ZoneOffset.of("+8")).toEpochMilli() < System.currentTimeMillis()) {
                return err("ticket-overtime", "优惠券已过期");
            }
            if (!ticket.getUserId().equals(model.getUserId())) {
                return err("ticket-not-owner", "优惠券不属于你");
            }
        }
        BigDecimal totalPrice = new BigDecimal("0");

        BsTravelgroupMaintuortravellinerecordRecord record = dslContext.selectFrom(BS_TRAVELGROUP_MAINTUORTRAVELLINERECORD).where(BS_TRAVELGROUP_MAINTUORTRAVELLINERECORD.ID.eq(model.getTuorTravelGroupId())).fetchOne();
        if (record == null) {
            return err("not-exist", "团行程不存在");
        }
        Gson gson = new Gson();
        java.util.List<String> carTypes = gson.fromJson(record.getPretravelcarlist(), new TypeToken<List<String>>() {
        }.getType());
        //车辆预算
        java.util.List<BsPreTravelCarPriceDTO> carPrices = new ArrayList<>();
        try {
            carPrices = dslContext.selectFrom(BS_PRETRAVELCARPRICE).where(BS_PRETRAVELCARPRICE.TRASH.eq(false).and(BS_PRETRAVELCARPRICE.LEVELTYPE.in(carTypes.toArray(new String[carTypes.size()]))).and(BS_PRETRAVELCARPRICE.DAYNUM.eq(record.getTraveldays()))).fetch().into(BsPreTravelCarPriceDTO.class);
        } catch (Exception e) {
            e.printStackTrace();
            return err("car-price-err", "车辆费用获取异常");
        }
        //住宿费用
        java.util.List<BsHotelRoomPriceDTO> hotelRoomPrices = new ArrayList<>();
        try {
            hotelRoomPrices = dslContext.selectFrom(BS_HOTELROOMPRICE).where(BS_HOTELROOMPRICE.TRASH.eq(false).and(BS_HOTELROOMPRICE.DAYNUM.eq(record.getTraveldays()))).fetch().into(BsHotelRoomPriceDTO.class);
        } catch (Exception e) {
            e.printStackTrace();
            return err("hotel-price-err", "酒店住宿费用获取异常");
        }
        java.util.Map<String, Object> datas = new HashMap<>();
        datas.put("carPrices", carPrices);
        datas.put("hotelRoomPrices", hotelRoomPrices);
        if (ticket != null) {
            datas.put("ticket", Map.of("ticketId", ticket.getId(), "ticketPrice", ticket.getPrice().toString()));//优惠券
        } else {
            datas.put("ticket", "{}");
        }
        String markPriceId = "" + model.getTuorTravelGroupId() + ":" + model.getUserId();
        redisTemplate.opsForValue().set(USER_JOIN_TOURTRAVELLINE_PRICELIST_PREFIX + markPriceId, gson.toJson(datas), 30, TimeUnit.MINUTES);
        datas.put("markPriceId", markPriceId);//产品预付费ID
        return suc(datas, 1, "suc", "操作成功");
    }

    /**
     * 02 创建人报名
     */

    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    @EqualsAndHashCode
    public static class Model_callbackTuorTravelLineOrderPrice {
        private String markPriceId;//产品预付费ID
    }

    /**
     * 回调费用
     *
     * @param model
     * @return
     */
//    public DataBean callbackTuorTravelLineOrderPrice(Model_callbackTuorTravelLineOrderPrice model) {
//        String[] ids = model.getMarkPriceId().split(":");//1.行程ID；2.用户ID
//        try{
//            redisTemplate.opsForValue().set(
//                    USER_JOIN_TOURTRAVELLINE_PRICELIST_PREFIX + model.getMarkPriceId(),
//                    "",
//                    30,
//                    TimeUnit.MINUTES
//            );
//            return DataBean.suc(true, 1, "suc", "操作成功");
//        }catch (Exception e){
//            e.printStackTrace();
//            return DataBean.err("trans-err", e.getMessage());
//        }
//    }

    /**
     * 上车点
     */
    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    @EqualsAndHashCode
    public static class _TourStartPoint_ {
        private String cityName;//城市
        private String address;//上车点
    }

    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    @EqualsAndHashCode
    public static class _AddValueProduct_ {
        private String shopProductId;
        private String originProductPrice;
    }

    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    @EqualsAndHashCode
    public static class Model_createPreTuorTravelLineOrder {
        private String userId;
        private String travelGroupId;
        private _TourStartPoint_ startPoint;
        //        private String startPoint;
        private java.util.Map<String, Object> orderExtInfor;
        //住宿费用
        private String hotelRoomPriceId;
        private String originHotelPrice;
        //车辆费用
        private String preTravelCarId;
        private String originTravelCarPrice;
        private java.util.Map<String, Object> carExtInfor;
        //个人报名信息
        private Enum_UserSex sex;
        private String realName;
        private String phone;
        private String idNum;
        private java.util.Map<String, Object> userExtInfor;
        //增值产品费用
        private java.util.List<_AddValueProduct_> addValueProductList;
        private java.util.Map<String, Object> addValueExtInfor;
    }

    /**
     * 查询出出团主记录
     *
     * @param travelGroupId
     * @return
     */
    public BsTravelgroupMaintuortravellinerecordRecord _getPreTravelGroupById(String travelGroupId) {
        return dslContext.selectFrom(BS_TRAVELGROUP_MAINTUORTRAVELLINERECORD).where(BS_TRAVELGROUP_MAINTUORTRAVELLINERECORD.ID.eq(travelGroupId)).fetchOne();
    }

    /**
     * 成为候补成员
     *
     * @param model
     * @return
     */
    public boolean _beMarkTravelLineOrder(Model_createPreTuorTravelLineOrder model, BsTravelgroupMaintuortravellinerecordRecord maingrouprecord) {
        try {
            return dslContext.transactionResult(ctx -> {
                Gson gson = new Gson();
                //1，保存报名记录
                String tourOrderId = "" + YitIdHelper.nextId();
                dslContext.insertInto(BS_TRAVELGROUP_TOURORDERRECORD).set(new BsTravelgroupTourorderrecordRecord(tourOrderId, Enum_TravelGroupTourOrderStats.Mark.getCode(), model.getUserId(), maingrouprecord.getId(), maingrouprecord.getStartdate() - DateUnit.DAY.getMillis(), System.currentTimeMillis(), false, new BigDecimal("0.00"), new BigDecimal("0.00"), gson.toJson(model.getStartPoint()), gson.toJson(Arrays.asList(new TOUR_TRAVELORDER_CTL(Enum_TravelGroupTourOrderStats.Waitpay, System.currentTimeMillis(), gson.fromJson(gson.toJson(model), new com.google.gson.reflect.TypeToken<java.util.Map<String, Object>>() {
                }.getType())))), gson.toJson(model.getOrderExtInfor()))).execute();
                //2，报名用户信息
                String userInforId = "" + YitIdHelper.nextId();

                java.util.Map<String, Object> userInforMap = model.getUserExtInfor();
                if (userInforMap == null) {
                    userInforMap = new HashMap<>();
                }
                userInforMap.put("V_userInforPhone", SecureUtil.des(MD5.create().digest(userInforId)).encryptBase64(model.getPhone(), "utf-8"));
                userInforMap.put("V_userInforIDNum", SecureUtil.des(MD5.create().digest(userInforId)).encryptBase64(model.getIdNum(), "utf-8"));
                dslContext.insertInto(BS_TRAVELGROUP_TOURUSERINFOR).set(new BsTravelgroupTouruserinforRecord(userInforId, tourOrderId, model.getSex().getCode(), model.getRealName(), DesensitizedUtil.mobilePhone(model.getPhone()), DesensitizedUtil.idCardNum(model.getIdNum(), 4, 4), gson.toJson(userInforMap))).execute();
                dslContext.commit();
                return true;
            });
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 检查报名人数，是否还可以报名，已满或超过返回true
     *
     * @param maxuserNum    当前最大报名人数
     * @param travelGroupId 路线ID
     * @return
     */
    public boolean _canMarkTravelLineOrder(Integer maxuserNum, String travelGroupId) {
        //要验证：wait；payed；join
        int count = dslContext.selectCount().from(BS_TRAVELGROUP_TOURORDERRECORD).where(BS_TRAVELGROUP_TOURORDERRECORD.TRAVELGROUPID.eq(travelGroupId).and(BS_TRAVELGROUP_TOURORDERRECORD.STATS.in(Enum_TravelGroupTourOrderStats.Waitpay.getCode(), Enum_TravelGroupTourOrderStats.Payed.getCode(), Enum_TravelGroupTourOrderStats.Join.getCode()))).fetchOne().value1();
        return maxuserNum <= count;//
    }

    /**
     * 检查报名人数，是否还可以报名，已满或超过返回true
     *
     * @param maxuserNum    当前最大报名人数
     * @param travelGroupId 路线ID
     * @return
     */
    public boolean _canMarkTravelLineOrder(Integer maxuserNum, String travelGroupId, int currentNum) {
        //要验证：wait；payed；join
        int count = dslContext.selectCount().from(BS_TRAVELGROUP_TOURORDERRECORD).where(BS_TRAVELGROUP_TOURORDERRECORD.TRAVELGROUPID.eq(travelGroupId).and(BS_TRAVELGROUP_TOURORDERRECORD.STATS.in(Enum_TravelGroupTourOrderStats.Waitpay.getCode(), Enum_TravelGroupTourOrderStats.Payed.getCode(), Enum_TravelGroupTourOrderStats.Join.getCode()))).fetchOne().value1();
        return (currentNum + count) >= maxuserNum;
    }

    /**
     * 报名
     *
     * @param model
     * @return
     */
    @Deprecated
    public DataBean createPreTuorTravelLineOrder(Model_createPreTuorTravelLineOrder model) {
        BsTravelgroupMaintuortravellinerecordRecord maingrouprecord = _getPreTravelGroupById(model.getTravelGroupId());
        if (maingrouprecord == null) {
            return err("travelline-mainrecord-err", "主记录异常");
        }
        if (maingrouprecord.getStats().equals(Enum_MainTourTravelLineStats.Trash.getCode())) {
            return err("travelline-mainrecord-err", "主记录已删除");
        }
        //验证是否可以报名
        boolean canCreate = _checkCanCreateTourTravelLine(model.getUserId(), maingrouprecord.getStartdate(), maingrouprecord.getTraveldays());
        if (!canCreate) {
            return err("cant-create", "期间你已经创建过团，无法再创建");
        }
        //检查是否已经抱团
        String turTravelLineId = _hasJoinTourTravelLine(model.getUserId(), DateUtil.formatDate(new Date(maingrouprecord.getStartdate())), maingrouprecord.getTraveldays());
        if (turTravelLineId != null) {
            return err("already-join", "你已经参与了旅游团");
        }
        //验证费用是否正常
        Gson gson = new Gson();
        String _priceListRecord = redisTemplate.opsForValue().get(USER_JOIN_TOURTRAVELLINE_PRICELIST_PREFIX + maingrouprecord.getId() + ":" + model.getUserId());
        if (_priceListRecord == null) {
            _beMarkTravelLineOrder(model, maingrouprecord);
            return err("pricelist-err", "费用表异常");
        }

        //上锁，避免报名人数超出
        RLock lock = redissonClient.getFairLock(TOUR_TRAVELLINE_ORDER_LOCK);
        try {
            lock.tryLock(30, TimeUnit.SECONDS);
            //验证报名人数
            if (_canMarkTravelLineOrder(maingrouprecord.getMaxusernum(), model.getTravelGroupId())) {
                return err("cant-mark", "报名人数已满，您已是候补");
            }
            java.util.Map<String, Object> priceListMap = gson.fromJson(_priceListRecord, new TypeToken<java.util.Map<String, Object>>() {
            }.getType());
            java.util.List<BsPreTravelCarPriceDTO> carPrices = null;
            try {
                carPrices = gson.fromJson(gson.toJson(priceListMap.get("carPrices")), new TypeToken<java.util.List<BsPreTravelCarPriceDTO>>() {
                }.getType());
            } catch (Exception e) {
                e.printStackTrace();
            }
            java.util.List<BsHotelRoomPriceDTO> hotelRoomPrices = null;
            try {
                hotelRoomPrices = gson.fromJson(gson.toJson(priceListMap.get("hotelRoomPrices")), new TypeToken<java.util.List<BsHotelRoomPriceDTO>>() {
                }.getType());
            } catch (Exception e) {
                e.printStackTrace();
            }

            BigDecimal totalPrice = new BigDecimal(0);


            //1.住宿费
            boolean checkSuc = false;
            for (BsHotelRoomPriceDTO room : hotelRoomPrices) {
                if (room.getId().equals(model.getHotelRoomPriceId())) {
                    if (room.getPrice().setScale(2, RoundingMode.HALF_UP).equals(new BigDecimal(model.getOriginHotelPrice()).setScale(2, RoundingMode.HALF_UP))) {
                        checkSuc = true;
                        totalPrice = totalPrice.add(new BigDecimal(model.getOriginHotelPrice()));
                        break;
                    }
                }
            }
            if (!checkSuc) {
                return err("hotel-price-err", "住宿价格异常");
            }
            checkSuc = false;
            //2.车辆费
            for (BsPreTravelCarPriceDTO car : carPrices) {
                if (car.getId().equals(model.getPreTravelCarId())) {
//                log.info("正在比对车辆价格：记录价格->{}   提交价格->{}",car.getPrice(),model.getOriginTravelCarPrice());
                    if (car.getPrice().setScale(2, RoundingMode.HALF_UP).equals(new BigDecimal(model.getOriginTravelCarPrice()).setScale(2, RoundingMode.HALF_UP))) {
                        totalPrice = totalPrice.add(new BigDecimal(model.getOriginTravelCarPrice()));
                        checkSuc = true;
                        break;
                    }
                }
            }
            if (!checkSuc) {
                return err("car-price-err", "车辆价格异常");
            }
            //3.增值产品价格
            if (!(model.getAddValueProductList() == null || model.getAddValueProductList().isEmpty())) {
                java.util.Set<String> productIds = new HashSet<>();
                for (_AddValueProduct_ ad : model.getAddValueProductList()) {
                    productIds.add(ad.getShopProductId());
                }
                java.util.Map<String, CoupleShopPdtRecord> pdtlistmap = basicBusinessImpl._getShopProductListByIds(productIds.stream().toList()).stream().collect(Collectors.toMap(CoupleShopPdtRecord::getId, Function.identity()));

                for (_AddValueProduct_ ad : model.getAddValueProductList()) {
                    CoupleShopPdtRecord sp = pdtlistmap.get(ad.getShopProductId());
                    if (sp == null) {
                        return err("add-value-product-err", "增值服务异常:" + ad.getShopProductId());
                    }
                    if (!sp.getPrice().setScale(2, RoundingMode.HALF_UP).equals(new BigDecimal(ad.getOriginProductPrice()).setScale(2, RoundingMode.HALF_UP))) {
                        return err("add-value-product-price-err", "增值服务价格异常:" + ad.getShopProductId());
                    }
                    totalPrice = totalPrice.add(new BigDecimal(ad.getOriginProductPrice()));
                }
            }

            try {
                final BigDecimal originPrice = totalPrice;
                return dslContext.transactionResult(ctx -> {
                    //1，保存报名记录
                    String tourOrderId = "" + YitIdHelper.nextId();
                    dslContext.insertInto(BS_TRAVELGROUP_TOURORDERRECORD).set(new BsTravelgroupTourorderrecordRecord(tourOrderId, Enum_TravelGroupTourOrderStats.Waitpay.getCode(), model.getUserId(), maingrouprecord.getId(), System.currentTimeMillis() + DateUnit.MINUTE.getMillis() * 30l, System.currentTimeMillis(), false, originPrice, originPrice, gson.toJson(model.getStartPoint()),
//                                            model.getStartPoint(),
                            gson.toJson(Arrays.asList(new TOUR_TRAVELORDER_CTL(Enum_TravelGroupTourOrderStats.Waitpay, System.currentTimeMillis(), gson.fromJson(gson.toJson(model), new com.google.gson.reflect.TypeToken<java.util.Map<String, Object>>() {
                            }.getType())))), gson.toJson(model.getOrderExtInfor()))).execute();
                    //2，报名用户信息
                    String userInforId = "" + YitIdHelper.nextId();

                    java.util.Map<String, Object> userInforMap = model.getUserExtInfor();
                    if (userInforMap == null) {
                        userInforMap = new HashMap<>();
                    }
                    userInforMap.put("V_userInforPhone", SecureUtil.des(MD5.create().digest(userInforId)).encryptBase64(model.getPhone(), "utf-8"));
                    userInforMap.put("V_userInforIDNum", SecureUtil.des(MD5.create().digest(userInforId)).encryptBase64(model.getIdNum(), "utf-8"));

                    dslContext.insertInto(BS_TRAVELGROUP_TOURUSERINFOR).set(new BsTravelgroupTouruserinforRecord(userInforId, tourOrderId, model.getSex().getCode(), model.getRealName(), DesensitizedUtil.mobilePhone(model.getPhone()), DesensitizedUtil.idCardNum(model.getIdNum(), 4, 4), gson.toJson(userInforMap))).execute();

                    //3，住房价
                    String roomId = "" + YitIdHelper.nextId();
                    dslContext.insertInto(BS_TRAVELGROUP_TOURORDERHOTELROOMRECORD).set(new BsTravelgroupTourorderhotelroomrecordRecord(roomId, model.getUserId(), tourOrderId, model.getHotelRoomPriceId(), System.currentTimeMillis(), new BigDecimal(model.getOriginHotelPrice()))).execute();
                    //4，行程费用
                    String carPriceId = "" + YitIdHelper.nextId();
                    dslContext.insertInto(BS_TRAVELGROUP_TOURCARPRICERECORD).set(new BsTravelgroupTourcarpricerecordRecord(carPriceId, model.getUserId(), tourOrderId, model.getPreTravelCarId(), System.currentTimeMillis(), new BigDecimal(model.getOriginTravelCarPrice()), new BigDecimal(model.getOriginTravelCarPrice()), gson.toJson(model.getCarExtInfor()))).execute();
                    //5，增值产品费用
                    if (!(model.getAddValueProductList() == null || model.getAddValueProductList().isEmpty())) {
                        java.util.List<BsTravelgroupTourordershopproductrecordRecord> addprice = new ArrayList<>();
                        for (_AddValueProduct_ ad : model.getAddValueProductList()) {
                            String orderShopProductId = "" + YitIdHelper.nextId();
                            addprice.add(new BsTravelgroupTourordershopproductrecordRecord(orderShopProductId, Enum_TravelGroupTourOrderShopProductStats.WaitOff.getCode(), model.getUserId(), tourOrderId, ad.getShopProductId(), "0", System.currentTimeMillis(), new BigDecimal(ad.getOriginProductPrice()), 0l, gson.toJson(model.getAddValueExtInfor())));
                        }
                    }

                    //6，报名成功，锁定
                    _lockJoinTourTravelLine(maingrouprecord.getId(), model.getUserId(), DateUtil.formatDate(new Date(maingrouprecord.getStartdate())), maingrouprecord.getTraveldays());

                    //7，验证是否是拥有者
                    if (maingrouprecord.getCreateuserid().equals(model.getUserId())) {
                        //修改开放状态
                        dslContext.update(BS_TRAVELGROUP_MAINTUORTRAVELLINERECORD).set(BS_TRAVELGROUP_MAINTUORTRAVELLINERECORD.STATS, Enum_MainTourTravelLineStats.Wait.getCode()).where(BS_TRAVELGROUP_MAINTUORTRAVELLINERECORD.ID.eq(maingrouprecord.getId())).execute();
                    }
                    dslContext.commit();
                    return suc(tourOrderId, 1, "suc", "报名成功");
                });
            } catch (Exception e) {
                e.printStackTrace();
                return err("trans-err", e.getMessage());
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
            return err("err", e.getMessage());
        } finally {
            lock.unlock();
        }

    }

    /**
     * 03 路线开放
     */

    /**
     * 04 团员搜索路线
     */

    /**
     * 05 成员报名
     */

    /**
     * 06 缴费
     */

    /**
     * 07 退团
     */

    /**
     * 08 开团
     */

    /**
     * 09 调度
     */

    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    @EqualsAndHashCode
    public static class Model_getMainTravelLineRecordById {
        private String id;
    }

    /**
     * 报名以及候补报名人数
     */
    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    @EqualsAndHashCode
    public static class _REPORT_MARK_PEOPLENUM_ {
        private Integer reportNum;// 报名人数
        private Integer markNum;//候补人数
    }

    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    @EqualsAndHashCode
    public static class _ORDER_RECORD_SIMPLE {
        private String userId;
        private String stats;
    }

    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    @EqualsAndHashCode
    public static class VPO_getMainTravelLineRecordById_Comment {
        private String id;
        @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
        @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
        private LocalDateTime createTime;
        private String content;
        private Integer zan;
        private String userId;
        private String nickName;
        private String cover;
    }

    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    @EqualsAndHashCode
    public static class _CityCode_ {
        private String cityId;
        private String cityName;
        private String cityCode;
    }

    /**
     * 查询小团详情
     *
     * @param model
     * @return
     */
    public DataBean getMainTravelLineRecordById(Model_getMainTravelLineRecordById model) {
        try {
            return dslContext.transactionResult(ctx -> {
                //表详情
                BsTravelGroupMainTuorTravelLineRecordDTO mainModel = dslContext.selectFrom(BS_TRAVELGROUP_MAINTUORTRAVELLINERECORD).where(BS_TRAVELGROUP_MAINTUORTRAVELLINERECORD.ID.eq(model.getId())).limit(1).fetchOneInto(BsTravelGroupMainTuorTravelLineRecordDTO.class);
                if (mainModel == null) {
                    return DataBean.errEmpty();
                }

                CountDownLatch latch = new CountDownLatch(6);

                //出发城市
                Future<_CityCode_> startFromCityFuture = queryService.submit(new Callable<_CityCode_>() {
                    @Override
                    public _CityCode_ call() throws Exception {
                        _CityCode_ dto = new _CityCode_();
                        try {
                            dto = dslContext.resultQuery("SELECT city_id as cityId,name as cityName,cityCode FROM `couple_main`.`sys_category` WHERE `city_id` = ? LIMIT 1", mainModel.getStartFromCityId()).fetchOneInto(_CityCode_.class);
                        } catch (Exception e) {
                            e.printStackTrace();
                        } finally {
                            latch.countDown();
                        }
                        return dto;
                    }
                });

                //创立人信息
                Future<BsUserLayoutUserInforDTO> creatorInforFuture = queryService.submit(new Callable<BsUserLayoutUserInforDTO>() {
                    @Override
                    public BsUserLayoutUserInforDTO call() throws Exception {
                        BsUserLayoutUserInforDTO dto = new BsUserLayoutUserInforDTO();
                        try {
                            dto = dslContext.selectFrom(BS_USERLAYOUT_USERINFOR).where(BS_USERLAYOUT_USERINFOR.ID.eq(mainModel.getCreateUserId())).limit(1).fetchOneInto(BsUserLayoutUserInforDTO.class);
                        } catch (Exception e) {
                            e.printStackTrace();
                        } finally {
                            latch.countDown();
                        }
                        return dto;
                    }
                });

                //查询发起人说
                Future<BsTravelGroupCreatorSayDTO> creatorSayFuture = queryService.submit(new Callable<BsTravelGroupCreatorSayDTO>() {
                    @Override
                    public BsTravelGroupCreatorSayDTO call() throws Exception {
                        try {
                            BsTravelGroupCreatorSayDTO dto = dslContext.selectFrom(BS_TRAVELGROUP_CREATORSAY).where(BS_TRAVELGROUP_CREATORSAY.TRAVELGROUPID.eq(model.getId())).limit(1).fetchOneInto(BsTravelGroupCreatorSayDTO.class);
                            return dto;
                        } finally {
                            latch.countDown();
                        }
                    }
                });
                //查询报名人数
                Future<_REPORT_MARK_PEOPLENUM_> peoplenumFuture = queryService.submit(new Callable<_REPORT_MARK_PEOPLENUM_>() {
                    @Override
                    public _REPORT_MARK_PEOPLENUM_ call() throws Exception {
                        try {
                            java.util.List<_ORDER_RECORD_SIMPLE> ls = dslContext.select(BS_TRAVELGROUP_TOURORDERRECORD.USERID.as("userId"), BS_TRAVELGROUP_TOURORDERRECORD.STATS.as("stats")).from(BS_TRAVELGROUP_TOURORDERRECORD).where(BS_TRAVELGROUP_TOURORDERRECORD.STATS.in(Enum_TravelGroupTourOrderStats.Waitpay.getCode(), Enum_TravelGroupTourOrderStats.Join.getCode(), Enum_TravelGroupTourOrderStats.Payed.getCode(), Enum_TravelGroupTourOrderStats.Mark.getCode())).and(BS_TRAVELGROUP_TOURORDERRECORD.TRAVELGROUPID.eq(model.getId())).fetchInto(_ORDER_RECORD_SIMPLE.class);
                            int marknum = 0;
                            int reportnum = 0;
                            for (_ORDER_RECORD_SIMPLE s : ls) {
                                if (s.getStats().equals(Enum_TravelGroupTourOrderStats.Mark.getCode())) {
                                    marknum++;
                                } else {
                                    reportnum++;
                                }
                            }
                            _REPORT_MARK_PEOPLENUM_ rs = new _REPORT_MARK_PEOPLENUM_(reportnum, marknum);
                            return rs;
                        } finally {
                            latch.countDown();
                        }
                    }
                });
                //查询评论
                Future<java.util.List<VPO_getMainTravelLineRecordById_Comment>> commentListFuture = queryService.submit(new Callable<List<VPO_getMainTravelLineRecordById_Comment>>() {
                    @Override
                    public List<VPO_getMainTravelLineRecordById_Comment> call() throws Exception {
                        try {
                            return dslContext.select(COUPLE_COMMENT.ID.as("id"), COUPLE_COMMENT.CREATE_TIME.as("createTime"), COUPLE_COMMENT.CONTENT.as("content"), COUPLE_COMMENT.ZAN_NUM.as("zan"), BS_USERLAYOUT_USERINFOR.ID.as("userId"), BS_USERLAYOUT_USERINFOR.NICKNAME.as("nickName"), BS_USERLAYOUT_USERINFOR.COVER.as("cover")).from(DSL.select(COUPLE_COMMENT.ID.as("id")).from(COUPLE_COMMENT).where(COUPLE_COMMENT.STATS.eq(Enum_CommentStats.Apply.getCode())).and(COUPLE_COMMENT.COMMENT_TYPE.eq(Enum_CommentType.TourMainTravel.getCode())).and(COUPLE_COMMENT.MAIN_ID.eq(model.getId())).orderBy(COUPLE_COMMENT.IS_TOP.desc(), COUPLE_COMMENT.CREATE_TIME.desc()).limit(0, 5).asTable("t")).leftJoin(COUPLE_COMMENT).on(COUPLE_COMMENT.ID.eq("t.id")).leftJoin(BS_USERLAYOUT_USERINFOR).on(BS_USERLAYOUT_USERINFOR.ID.eq(COUPLE_COMMENT.USER_ID)).fetchInto(VPO_getMainTravelLineRecordById_Comment.class);
                        } finally {
                            latch.countDown();
                        }
                    }
                });

                Future<BsTravelLinePlatPreTravelLineDTO> pretravellineFuture = queryService.submit(new Callable<BsTravelLinePlatPreTravelLineDTO>() {

                    @Override
                    public BsTravelLinePlatPreTravelLineDTO call() throws Exception {
                        BsTravelLinePlatPreTravelLineDTO dto = new BsTravelLinePlatPreTravelLineDTO();
                        try {
                            dto = dslContext.selectFrom(BS_TRAVELLINE_PLATPRETRAVELLINE).where(BS_TRAVELLINE_PLATPRETRAVELLINE.ID.eq(mainModel.getPreTravelLineId())).limit(1).fetchOneInto(BsTravelLinePlatPreTravelLineDTO.class);
                            return dto;
                        } catch (Exception e) {
                            e.printStackTrace();
                        } finally {
                            latch.countDown();
                        }
                        return dto;
                    }
                });

                latch.await(30, TimeUnit.SECONDS);
                dslContext.commit();
                _REPORT_MARK_PEOPLENUM_ pn = peoplenumFuture.get();
                java.util.Map<String, Object> ds = new HashMap<>();
                //
//                ds.put("preTravelLine", pretravellineFuture.get());
//                ds.put("creatorInfor", creatorInforFuture.get());
//                ds.put("travelDetail", mainModel);
//                ds.put("creatorSay", creatorSayFuture.get());
//                ds.put("markNum", pn.getMarkNum());
//                ds.put("reportNum", pn.getReportNum());
//                ds.put("comments", commentListFuture.get());


                ds.put("preTravelLine", pretravellineFuture.get());
                ds.put("creatorInfor", creatorInforFuture.get());
                ds.put("travelDetail", mainModel);
                ds.put("creatorSay", creatorSayFuture.get());
                ds.put("markNum", pn.getMarkNum());
                ds.put("reportNum", pn.getReportNum());
                ds.put("comments", commentListFuture.get());
                ds.put("startFromCityCode", startFromCityFuture.get());

                return suc(ds, 1, "suc", "操作成功");
            });
        } catch (Exception e) {
            e.printStackTrace();
            return err("trans-err", e.getMessage());
        }
    }


    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    @EqualsAndHashCode
    public static class Model_updateTourTravelLineGroup {
        private String travelGroupId;//旅游团ID
        private Boolean forceUpdate;//是否强行更改信息
        private String startFromCityId;//出发城市ID
        private String startFromCityTitle;//出发城市名
        private String createUserId;//创建者ID
        private String preTravelLineId;//旅游路线ID
        private String startDate;//开始日期
        private Integer travelDays;//旅游天数
        private Integer maxUserNum;//最大人数
        private java.util.Map<String, Object> extInfor;//其他信息
        private java.util.List<Enum_CarDetailType> preTravelCarList;//选择车辆
        private java.util.List<_TravelLine_DayScenic_> dayScenicList;//每日景点
    }

    /**
     * 修改团信息
     *
     * @param model
     * @return
     */
    public DataBean updateTuorTravelLineGroup(Model_updateTourTravelLineGroup model) {
        if (model.getForceUpdate() == null) {
            model.setForceUpdate(false);
        }
        try {
            return dslContext.transactionResult(ctx -> {

                Long startDate = DateUtil.parseDate(model.getStartDate()).getTime();
                Long today = DateUtil.parseDate(DateUtil.today()).getTime();

                //统计是否已有报名人数
                if (!model.getForceUpdate()) {

                    int count = dslContext.selectCount().from(BS_TRAVELGROUP_TOURORDERRECORD).where(BS_TRAVELGROUP_TOURORDERRECORD.TRAVELGROUPID.eq(model.getTravelGroupId())).and(BS_TRAVELGROUP_TOURORDERRECORD.STATS.in(Enum_TravelGroupTourOrderStats.Waitpay.getCode(), Enum_TravelGroupTourOrderStats.Join.getCode(), Enum_TravelGroupTourOrderStats.Payed.getCode())).groupBy(BS_TRAVELGROUP_TOURORDERRECORD.TRAVELGROUPID).fetchOne().value1();
                    return err("exist-people", "已有" + count + "人报名-");
                }
                //
                BsTravellinePlatpretravellineRecord preTravelLine = _getPreTravelLineById(model.getPreTravelLineId());

                Gson gson = new Gson();
                BsTravelgroupMaintuortravellinerecordRecord mainRecord = dslContext.selectFrom(BS_TRAVELGROUP_MAINTUORTRAVELLINERECORD).where(BS_TRAVELGROUP_MAINTUORTRAVELLINERECORD.ID.eq(model.getTravelGroupId())).fetchOne();
                mainRecord.setPretravellineid(model.getPreTravelLineId());
                mainRecord.setTenantid(preTravelLine.getTenantid());
                mainRecord.setStartdate(startDate);
                mainRecord.setTraveldays(model.getTravelDays());
                mainRecord.setMaxusernum(model.getMaxUserNum());
                mainRecord.setStartfromcityid(model.getStartFromCityId());
                mainRecord.setContractid(preTravelLine.getContractid());
                mainRecord.setInsuranceid(preTravelLine.getInsuranceid());
                mainRecord.setExpiredate(startDate - DateUnit.HOUR.getMillis() * 12);
                mainRecord.setStrartfromcitytitle(model.getStartFromCityTitle());
                mainRecord.setTraveltitle(preTravelLine.getPrelinename());
                mainRecord.setExtinfor(gson.toJson(model.getExtInfor()));
                mainRecord.setPretravelcarlist(gson.toJson(model.getPreTravelCarList()));
                mainRecord.setTravellineremark(gson.toJson(model.getDayScenicList()));
                mainRecord.update();

                //修改出发城市
                dslContext.update(BS_TRAVELGROUP_STARTFROMCITY).set(BS_TRAVELGROUP_STARTFROMCITY.CITYID, model.getStartFromCityId()).where(BS_TRAVELGROUP_STARTFROMCITY.TRASH.eq(false)).and(BS_TRAVELGROUP_STARTFROMCITY.TRAVELGROUPID.eq(model.getTravelGroupId())).execute();


                dslContext.commit();
                return suc(true, 1, "suc", "操作成功");
            });
        } catch (Exception e) {
            e.printStackTrace();
            return err("trans-err", e.getMessage());
        }
    }


    private BsMyContactPeopleDTO getMyContactPeopleByTypeNum(String userId, String type, String num) {
        return dslContext.selectFrom(BS_MYCONTACTPEOPLE).where(BS_MYCONTACTPEOPLE.TRASH.eq(false)).and(BS_MYCONTACTPEOPLE.GROUPUSERID.eq(userId)).and(BS_MYCONTACTPEOPLE.CARDTYPE.eq(type)).and(BS_MYCONTACTPEOPLE.CARDNUM.eq(num)).limit(1).fetchOneInto(BsMyContactPeopleDTO.class);
    }

    //01 新增我的联系人列表
    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    @EqualsAndHashCode
    public static class Model_createMyContactPeople {
        private String userId;
        private String realName;
        private Enum_UserSex sex;
        private Enum_UserIDType idType;
        private String cardNum;
        private String birthDay;
        private String contactTel;
    }

    /**
     * 新增我的联系人
     *
     * @param model
     * @return
     */
    public DataBean createMyContactPeople(Model_createMyContactPeople model) {
        BsMyContactPeopleDTO existDto = getMyContactPeopleByTypeNum(model.getUserId(), model.getIdType().getCode(), model.getCardNum());
        if (existDto != null) {
            return err("exist-people", "已有该联系人");
        }
        try {
            return dslContext.transactionResult(ctx -> {
                String id = "" + YitIdHelper.nextId();
                //先检查同组别下 相同身份类型与值相同得人
                dslContext.insertInto(BS_MYCONTACTPEOPLE).set(new BsMycontactpeopleRecord(id, false, model.getUserId(), model.getRealName(), model.getIdType().getCode(), model.getCardNum(), model.getBirthDay(), model.getSex().getCode(), model.getContactTel(), System.currentTimeMillis())).execute();

                dslContext.commit();
                return suc(id, 1, "suc", "操作成功");
            });
        } catch (Exception e) {
            e.printStackTrace();
            return err("trans-err", e.getMessage());
        }
    }

    //02 查询我的联系人列表
    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    @EqualsAndHashCode
    public static class Model_getMyContactPeopleList {
        private String userId;
    }

    /**
     * 获取我的联系人列表
     *
     * @param model
     * @return
     */
    public DataBean getMyContactPeopleList(Model_getMyContactPeopleList model) {
        try {
            return dslContext.transactionResult(ctx -> {
                //todo
                java.util.List<BsMyContactPeopleDTO> list = dslContext.selectFrom(BS_MYCONTACTPEOPLE).where(BS_MYCONTACTPEOPLE.TRASH.eq(false)).and(BS_MYCONTACTPEOPLE.GROUPUSERID.eq(model.getUserId())).fetchInto(BsMyContactPeopleDTO.class);
                dslContext.commit();
                if (list == null || list.isEmpty()) {
                    return DataBean.sucEmpty();
                }
                return suc(list, list.size(), "suc", "操作成功");
            });
        } catch (Exception e) {
            e.printStackTrace();
            return err("trans-err", e.getMessage());
        }
    }

    //03 修改我的联系人列表
    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    @EqualsAndHashCode
    public static class Model_updateMyContactPeople {
        private String contactId;
        private String userId;
        private String realName;
        private Enum_UserSex sex;
        private Enum_UserIDType idType;
        private String cardNum;
        private String birthDay;
        private String contactTel;
    }

    /**
     * 修改我的联系人信息
     *
     * @param model
     * @return
     */
    public DataBean updateMyContactPeople(Model_updateMyContactPeople model) {
        BsMyContactPeopleDTO existDto = getMyContactPeopleByTypeNum(model.getUserId(), model.getIdType().getCode(), model.getCardNum());
        if (existDto != null) {
            if (!existDto.getId().equals(model.getContactId())) return err("exist-people", "已有该联系人");
        }
        try {
            return dslContext.transactionResult(ctx -> {
                dslContext.update(BS_MYCONTACTPEOPLE).set(BS_MYCONTACTPEOPLE.REALNAME, model.getRealName()).set(BS_MYCONTACTPEOPLE.SEX, model.getSex().getCode()).set(BS_MYCONTACTPEOPLE.CARDTYPE, model.getIdType().getCode()).set(BS_MYCONTACTPEOPLE.CARDNUM, model.getCardNum()).set(BS_MYCONTACTPEOPLE.BIRTHDAY, model.getBirthDay()).set(BS_MYCONTACTPEOPLE.CONTACTTEL, model.getContactTel()).where(BS_MYCONTACTPEOPLE.ID.eq(model.getContactId())).execute();
                dslContext.commit();
                return suc(true, 1, "suc", "操作成功");
            });
        } catch (Exception e) {
            e.printStackTrace();
            return err("trans-err", e.getMessage());
        }
    }

    //04 删除我的联系人列表
    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    @EqualsAndHashCode
    public static class Model_trashMyContactPeople {
        private String userId;
        private String contactId;
    }

    /**
     * 删除我的联系人
     *
     * @param model
     * @return
     */
    public DataBean trashMyContactPeople(Model_trashMyContactPeople model) {
        try {
            return dslContext.transactionResult(ctx -> {
                dslContext.update(BS_MYCONTACTPEOPLE).set(BS_MYCONTACTPEOPLE.TRASH, true).where(BS_MYCONTACTPEOPLE.ID.eq(model.getContactId())).and(BS_MYCONTACTPEOPLE.GROUPUSERID.eq(model.getUserId())).execute();
                dslContext.commit();
                return suc(true, 1, "suc", "操作成功");
            });
        } catch (Exception e) {
            e.printStackTrace();
            return err("trans-err", e.getMessage());
        }
    }

    //报名大团
    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    @EqualsAndHashCode
    public static class Model_provideTravelListGroupOrderBudget {
        private String userId;
        private String travelId;
        private String ticketId;
    }

    /**
     * 大团预算费用
     *
     * @param model
     * @return
     */
    @Deprecated
    public DataBean provideTravelListGroupOrderBudget(Model_provideTravelListGroupOrderBudget model) {
        if (System.currentTimeMillis() > 0) {
            err("api-err", "api已废弃");
        }
        try {
            return dslContext.transactionResult(ctx -> {

                dslContext.commit();
                return suc(true, 1, "suc", "操作成功");
            });
        } catch (Exception e) {
            e.printStackTrace();
            return err("trans-err", e.getMessage());
        }
    }


    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    @EqualsAndHashCode
    public static class Model_createTourTravelStep1 {
        private String userId;
        private String travelGroupId;
        //        private _TourStartPoint_ startPoint;
        private String startPoint;
        private String ticketId;
        private String insuranceId;//保险ID
        //        private String startPoint;
        private java.util.Map<String, Object> orderExtInfor;
        //住宿费用
        private String hotelRoomPriceId;
        //        private String originHotelPrice;
        //车辆费用
        private String preTravelCarId;
        //        private String originTravelCarPrice;
        private java.util.Map<String, Object> carExtInfor;
        //        private java.util.Map<String, Object> userExtInfor;
        //增值产品费用
//        private java.util.List<String> addValueProductIds;
        private java.util.List<String> contactPeopleIds;//报名人ID
        private java.util.Map<String, Integer> addValueInfor;//增值服务产品Id-数量
    }

    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    @EqualsAndHashCode
    public static class _STEP_PRICE_MODEL_ {
        //[{"minNum":1,"price":"66","maxNum":5}]
        private Integer minNum;//最小人数
        private String price;//金额
        private Integer maxNum;//最大人数
    }


    /**
     * 成为候补成员
     *
     * @param userId
     * @param contactUserId
     * @param travelGroupId
     * @param payExpireTime
     * @param startPoint
     * @param orderExtInfor
     * @param myContactPeopleDTO
     * @return
     */
    public boolean _beMarkTravelLineOrderv2(String userId, String contactUserId, String travelGroupId, Long payExpireTime, String startPoint, java.util.Map<String, Object> orderExtInfor, BsMyContactPeopleDTO myContactPeopleDTO

    ) {
        try {
            return dslContext.transactionResult(ctx -> {
                Gson gson = new Gson();
                //1，保存报名记录
                String tourOrderId = "" + YitIdHelper.nextId();
                dslContext.insertInto(BS_TRAVELGROUP_TOURORDERRECORD).set(new BsTravelgroupTourorderrecordRecord(tourOrderId, Enum_TravelGroupTourOrderStats.Mark.getCode(), userId, travelGroupId, payExpireTime, System.currentTimeMillis(), false, new BigDecimal("0.00"), new BigDecimal("0.00"), startPoint, "{}", gson.toJson(orderExtInfor))).execute();
                //2，报名用户信息
                String userInforId = "" + YitIdHelper.nextId();

                BsMyContactPeopleDTO cdto = new BsMyContactPeopleDTO(myContactPeopleDTO.getId(), myContactPeopleDTO.getTrash(), myContactPeopleDTO.getGroupUserId(), myContactPeopleDTO.getRealName(), myContactPeopleDTO.getCardType(), myContactPeopleDTO.getCardNum(), myContactPeopleDTO.getBirthDay(), myContactPeopleDTO.getSex(), myContactPeopleDTO.getContactTel(), myContactPeopleDTO.getCreateTime());

                cdto.setContactTel(SecureUtil.des(MD5.create().digest(userInforId)).encryptBase64(cdto.getContactTel(), "utf-8"));
                cdto.setCardNum(SecureUtil.des(MD5.create().digest(userInforId)).encryptBase64(cdto.getCardNum(), "utf-8"));
                dslContext.insertInto(BS_TRAVELGROUP_TOURUSERINFOR).set(new BsTravelgroupTouruserinforRecord(userInforId, tourOrderId, cdto.getSex(), cdto.getRealName(), DesensitizedUtil.mobilePhone(cdto.getContactTel()), DesensitizedUtil.idCardNum(cdto.getCardNum(), 4, 4), gson.toJson(cdto))).execute();
                dslContext.commit();
                return true;
            });
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 小团报名-第一步
     *
     * @param model
     * @return
     */
    public DataBean createTourTravelStep1(Model_createTourTravelStep1 model) {
        if (model.getPreTravelCarId() == null) {
            model.setPreTravelCarId("0");
        }
        BsTravelgroupMaintuortravellinerecordRecord maingrouprecord = _getPreTravelGroupById(model.getTravelGroupId());
        if (maingrouprecord == null) {
            return err("travelline-mainrecord-err", "主记录异常");
        }
        if (maingrouprecord.getStats().equals(Enum_MainTourTravelLineStats.Trash.getCode())) {
            return err("travelline-mainrecord-err", "主记录已删除");
        }
        //验证是否可以报名
        boolean canCreate = _checkCanCreateTourTravelLine(model.getUserId(), maingrouprecord.getStartdate(), maingrouprecord.getTraveldays());
        if (!canCreate) {
            return err("cant-create", "期间你已经创建过团，无法再创建");
        }
        //检查是否已经抱团
        for (String cid : model.getContactPeopleIds()) {
            String turTravelLineId = _hasJoinTourTravelLine(cid, DateUtil.formatDate(new Date(maingrouprecord.getStartdate())), maingrouprecord.getTraveldays());
            if (turTravelLineId != null) {
                return err("already-join", "出行时间已有人参与了其他旅游团");
            }
        }
        //验证是否可报名
        boolean canReport = switch (Enum_MainTourTravelLineStats.parseCode(maingrouprecord.getStats())) {
            case WaitOwner -> false;
            case TravelOver -> false;
            case Freze -> false;
            case Cancel -> false;
            case Trash -> false;
            case ApplyOk -> false;
            case Start -> false;
            case AlreadyFull -> false;
            default -> true;
        };
        if (!canReport) {
            return DataBean.err("cant-report", "当前状态【" + Enum_MainTourTravelLineStats.parseCode(maingrouprecord.getStats()).getTitle() + "】不能报名");
        }
        //验证是否延期
        if (System.currentTimeMillis() > maingrouprecord.getExpiredate()) {
            return err("expireTime-over", "超过报名时间");
        }


        boolean beMark[] = new boolean[1];//是否纳入候选
        //验证报名人数
        if (_canMarkTravelLineOrder(maingrouprecord.getMaxusernum(), model.getTravelGroupId(), model.getContactPeopleIds().size())) {
//            if (model.getContactPeopleIds().size() > 1) {
//                //超过报名人数纳入候选
//                return err("cant-mark", "已超过报名人数");//
//            } else {
//                BsMyContactPeopleDTO myContactPeopleDTO = dslContext.selectFrom(BS_MYCONTACTPEOPLE)
//                        .where(
//                                BS_MYCONTACTPEOPLE.TRASH.eq(false)
//                        ).and(
//                                BS_MYCONTACTPEOPLE.GROUPUSERID.eq(model.getUserId())
//                        ).and(BS_MYCONTACTPEOPLE.ID.in(model.getContactPeopleIds()))
//                        .limit(1)
//                        .fetchOneInto(BsMyContactPeopleDTO.class);
//                if (myContactPeopleDTO == null) {
//                    return err("contact-err", "联系人异常");
//                }
//                _beMarkTravelLineOrderv2(
//                        model.getUserId(),
//                        model.getContactPeopleIds().get(0),
//                        maingrouprecord.getId(),
//                        maingrouprecord.getStartdate() - DateUnit.DAY.getMillis(),
//                        new Gson().toJson(model.getStartPoint()),
//                        model.getOrderExtInfor(),
//                        myContactPeopleDTO
//                );
//                return err("user-mark", "已成为候补");
//            }
            beMark[0] = true;
        }

        //验证券
        CoupleUserDiscountCouponRecord ticket = null;
        if (model.getTicketId() != null) {
            //验证优惠券
            ticket = _checkTicket(model.getTicketId(), model.getUserId());
            if (ticket == null) {
                return err("ticket-err", "优惠券不存在");
            }
            if (ticket.getExpirationTime().toInstant(ZoneOffset.of("+8")).toEpochMilli() < System.currentTimeMillis()) {
                return err("ticket-overtime", "优惠券已过期");
            }
            if (!ticket.getUserId().equals(model.getUserId())) {
                return err("ticket-not-owner", "优惠券不属于你");
            }
        }
        CoupleUserDiscountCouponRecord finalticket = ticket;
        //计算总价
        String orderId = "" + YitIdHelper.nextId();
        try {
            return dslContext.transactionResult(ctx -> {
                BigDecimal totalPriceW = null;
                BigDecimal ticketPrice = null;
                BigDecimal groupStepPrice = null;
                BigDecimal carPrice = null;
                BigDecimal roomPrice = null;

                String ticketPriceStr = "0";//优惠券价格
                String groupStepPriceStr = "0";//阶梯价
                String carPriceStr = "0";//行程价
                String roomPriceStr = "0";//房价
                String insurancePriceStr = "0";//保险价
                String addPriceStr = "0";//增值服务价
                //上锁，避免报名人数超出
                RLock lock = redissonClient.getFairLock(TOUR_TRAVELLINE_ORDER_LOCK);
                try {
                    lock.tryLock(30, TimeUnit.SECONDS);
                    //验证报名人数
                    if (_canMarkTravelLineOrder(maingrouprecord.getMaxusernum(), model.getTravelGroupId())) {
                        return err("cant-mark", "报名人数已满，您已是候补");
                    }
                    //查询房价
                    Future<BsHotelRoomPriceDTO> roomFutrue = queryService.submit(new Callable<BsHotelRoomPriceDTO>() {
                        @Override
                        public BsHotelRoomPriceDTO call() throws Exception {
                            try {
                                BsHotelRoomPriceDTO hotelRoomPrices = dslContext.selectFrom(BS_HOTELROOMPRICE).where(BS_HOTELROOMPRICE.TRASH.eq(false).and(BS_HOTELROOMPRICE.DAYNUM.eq(maingrouprecord.getTraveldays())).and(BS_HOTELROOMPRICE.ID.eq(model.getHotelRoomPriceId()))).limit(1).fetchOneInto(BsHotelRoomPriceDTO.class);
                                return hotelRoomPrices;
                            } catch (Exception e) {
                                e.printStackTrace();
                                return null;
                            }
                        }
                    });
                    //查询车价
                    Future<BsPreTravelCarPriceDTO> carFutrue = queryService.submit(new Callable<BsPreTravelCarPriceDTO>() {
                        @Override
                        public BsPreTravelCarPriceDTO call() throws Exception {
                            String _carList = maingrouprecord.getPretravelcarlist();
                            java.util.List<String> carIdlist = new java.util.ArrayList<>();
                            try {
                                java.util.List<java.util.Map<String, Object>> carList = new Gson().fromJson(_carList, new TypeToken<java.util.List<java.util.Map<String, Object>>>() {
                                }.getType());
                                for (java.util.Map<String, Object> car : carList) {
                                    carIdlist.add(car.get("id").toString());
                                }
                            } catch (Exception e) {
                                java.util.List<String> carList = new Gson().fromJson(_carList, new TypeToken<java.util.List<String>>() {
                                }.getType());
                                carIdlist.addAll(carList);
                            }
                            try {
                                BsPreTravelCarPriceDTO preTravelCarPrices = dslContext.selectFrom(BS_PRETRAVELCARPRICE).where(BS_PRETRAVELCARPRICE.TRASH.eq(false).and(BS_PRETRAVELCARPRICE.DAYNUM.eq(maingrouprecord.getTraveldays())).and(BS_PRETRAVELCARPRICE.ID.in(carIdlist))).orderBy(BS_PRETRAVELCARPRICE.PRICE.desc()).limit(1).fetchOneInto(BsPreTravelCarPriceDTO.class);
                                return preTravelCarPrices;
                            } catch (Exception e) {
                                e.printStackTrace();
                                return null;
                            }

                        }
                    });
                    //查询保险价
                    Future<BsInsuranceDataDTO> insuranceFutrue = queryService.submit(new Callable<BsInsuranceDataDTO>() {
                        @Override
                        public BsInsuranceDataDTO call() throws Exception {
                            try {
                                BsInsuranceDataDTO insurancePrices = dslContext.selectFrom(BS_INSURANCEDATA).where(BS_INSURANCEDATA.TRASH.eq(false).and(BS_INSURANCEDATA.ID.eq(model.getInsuranceId())).and(BS_INSURANCEDATA.MINDAY.le(maingrouprecord.getTraveldays())).and(BS_INSURANCEDATA.MAXDAY.ge(maingrouprecord.getTraveldays()))).limit(1).fetchOneInto(BsInsuranceDataDTO.class);
                                return insurancePrices;
                            } catch (Exception e) {
                                e.printStackTrace();
                                return null;
                            }
                        }
                    });
                    //计算增值产品费用
                    Future<java.util.List<CoupleShopPdtDTO>> addPriceFuture = queryService.submit(new Callable<java.util.List<CoupleShopPdtDTO>>() {
                        @Override
                        public java.util.List<CoupleShopPdtDTO> call() throws Exception {
                            try {
                                java.util.List<CoupleShopPdtDTO> list = dslContext.selectFrom(COUPLE_SHOP_PDT).where(COUPLE_SHOP_PDT.ID.in(model.getAddValueInfor().keySet())).fetchInto(CoupleShopPdtDTO.class);
                                return list;
                            } catch (Exception e) {
                                e.printStackTrace();
                                return null;
                            }
                        }
                    });

                    //查询阶梯价
                    Future<BigDecimal> stepPriceFuture = queryService.submit(new Callable<BigDecimal>() {
                        @Override
                        public BigDecimal call() throws Exception {
                            String rs = dslContext.select(BS_TRAVELGROUP_TRAVELISTGROUP.STEPPRICE).from(BS_TRAVELGROUP_TRAVELISTGROUP).where(BS_TRAVELGROUP_TRAVELISTGROUP.ID.eq(DSL.select(BS_TRAVELGROUP_MAINTOURTRAVELRECORDBINDTRAVELLISTGROUP.TRAVELLISTGROUPID).from(BS_TRAVELGROUP_MAINTOURTRAVELRECORDBINDTRAVELLISTGROUP).where(BS_TRAVELGROUP_MAINTOURTRAVELRECORDBINDTRAVELLISTGROUP.MAINTOURTRAVELRECORDID.eq(maingrouprecord.getId())).limit(1))).limit(1).fetchOneInto(String.class);
                            Gson gson = new Gson();
                            try {
                                java.util.List<_STEP_PRICE_MODEL_> list = gson.fromJson(rs, new com.google.gson.reflect.TypeToken<java.util.List<_STEP_PRICE_MODEL_>>() {
                                }.getType());
                                for (_STEP_PRICE_MODEL_ m : list) {
                                    if (m.getMinNum() <= model.getContactPeopleIds().size() && model.getContactPeopleIds().size() <= m.getMaxNum()) {
                                        return new BigDecimal(m.getPrice());
                                    }
                                }
                                return null;
                            } catch (Exception e) {
                                return null;
                            }
                        }
                    });


                    BigDecimal totalPrice = new BigDecimal(0);
                    ticketPrice = finalticket == null ? new BigDecimal(0) : finalticket.getPrice();
                    if (maingrouprecord.getType().equals(Enum_TourTravelGroupType.Group.getCode())) {
                        try {
                            groupStepPrice = stepPriceFuture.get();
                        } catch (Exception e) {
                            e.printStackTrace();
                            return err("step-price-err", "阶梯价异常");
                        }
                    }
                    try {
                        roomPrice = roomFutrue.get().getPrice();
                    } catch (Exception e) {
                        e.printStackTrace();
                        return err("room-price-err", "住宿价异常");
                    }
                    if (maingrouprecord.getType().equals(Enum_TourTravelGroupType.Self.getCode())) {
                        try {
                            carPrice = carFutrue.get().getPrice();
                        } catch (Exception e) {
                            e.printStackTrace();
                            return err("car-price-err", "出行价异常");
                        }
                    }


                    java.util.List<CoupleShopPdtDTO> addProductList = addPriceFuture == null ? new ArrayList<>() : addPriceFuture.get();
                    {
                        //计算用券
                        if (model.getTicketId() != null) {
                            totalPrice = totalPrice.subtract(ticketPrice);
                            ticketPriceStr = ticketPrice.toString();
                        }
                        //计算车费
                        if (maingrouprecord.getType().equals(Enum_TourTravelGroupType.Self.getCode())) {
                            //小团费用
                            totalPrice = totalPrice.add(carPrice.multiply(new BigDecimal(model.getContactPeopleIds().size())));
                            carPriceStr = carPrice.multiply(new BigDecimal(model.getContactPeopleIds().size())).toString();
                        } else {
                            //大团费用
                            totalPrice = totalPrice.add(groupStepPrice.multiply(new BigDecimal(model.getContactPeopleIds().size())));
                            groupStepPriceStr = groupStepPrice.multiply(new BigDecimal(model.getContactPeopleIds().size())).toString();
                        }
                        //计算房间费
                        totalPrice = totalPrice.add(roomPrice.multiply(new BigDecimal(model.getContactPeopleIds().size())));
                        roomPriceStr = roomPrice.multiply(new BigDecimal(model.getContactPeopleIds().size())).toString();
                        //计算增值产品价格
                        BigDecimal tmpAddPrice = new BigDecimal(0);
                        if (!(model.getAddValueInfor() == null || model.getAddValueInfor().isEmpty())) {
                            java.util.List<CoupleShopPdtDTO> addPriceLIst = addProductList;
                            if (!(addPriceLIst == null || addPriceLIst.isEmpty())) {
                                for (CoupleShopPdtDTO dto : addPriceLIst) {
                                    totalPrice = totalPrice.add(dto.getPrice().multiply(new BigDecimal(model.getAddValueInfor().get(dto.getId()))));//给的原价
                                    tmpAddPrice = tmpAddPrice.add(dto.getPrice().multiply(new BigDecimal(model.getAddValueInfor().get(dto.getId()))));
                                }
                            }
                        }
                        addPriceStr = tmpAddPrice.toString();
                        //计算保险
                        totalPrice = totalPrice.add(insuranceFutrue.get().getPerPrice().multiply(new BigDecimal(model.getContactPeopleIds().size())));
                        insurancePriceStr = insuranceFutrue.get().getPerPrice().multiply(new BigDecimal(model.getContactPeopleIds().size())).toString();
                    }
                    Gson gson = new Gson();
                    //生成订单
                    model.getOrderExtInfor().put("insurancedetail", gson.toJson(insuranceFutrue.get()));
                    dslContext.insertInto(BS_TRAVELGROUP_TOURORDERRECORD).set(new BsTravelgroupTourorderrecordRecord(orderId, beMark[0] ? Enum_TravelGroupTourOrderStats.Mark.getCode() : Enum_TravelGroupTourOrderStats.Waitpay.getCode(), model.getUserId(), maingrouprecord.getId(), System.currentTimeMillis() + DateUnit.MINUTE.getMillis() * 30l, System.currentTimeMillis(), false, totalPrice, totalPrice,
//                                            gson.toJson(model.getStartPoint()),
                            model.getStartPoint(),
//                                            model.getStartPoint(),
                            gson.toJson(Arrays.asList(new TOUR_TRAVELORDER_CTL(Enum_TravelGroupTourOrderStats.Waitpay, System.currentTimeMillis(), gson.fromJson(gson.toJson(model), new com.google.gson.reflect.TypeToken<java.util.Map<String, Object>>() {
                            }.getType())))), gson.toJson(model.getOrderExtInfor()))).execute();
                    //报名信息
                    java.util.List<BsMyContactPeopleDTO> myContactPeopleDTOs = dslContext.selectFrom(BS_MYCONTACTPEOPLE).where(BS_MYCONTACTPEOPLE.TRASH.eq(false)).and(BS_MYCONTACTPEOPLE.GROUPUSERID.eq(model.getUserId())).and(BS_MYCONTACTPEOPLE.ID.in(model.getContactPeopleIds())).fetchInto(BsMyContactPeopleDTO.class);
                    if (myContactPeopleDTOs == null) {
                        throw new Exception("报名人信息异常");
                    }
                    for (BsMyContactPeopleDTO myContactPeopleDTO : myContactPeopleDTOs) {
                        String uid = "" + YitIdHelper.nextId();
                        String tel = myContactPeopleDTO.getContactTel();
                        myContactPeopleDTO.setContactTel(SecureUtil.des(MD5.create().digest(uid)).encryptBase64(myContactPeopleDTO.getContactTel(), "utf-8").replaceAll("\\u003d", "="));
                        String num = myContactPeopleDTO.getCardNum();
                        myContactPeopleDTO.setCardNum(SecureUtil.des(MD5.create().digest(uid)).encryptBase64(myContactPeopleDTO.getCardNum(), "utf-8").replaceAll("\\u003d", "="));
                        dslContext.insertInto(BS_TRAVELGROUP_TOURUSERINFOR).set(new BsTravelgroupTouruserinforRecord(uid, orderId, myContactPeopleDTO.getSex(), myContactPeopleDTO.getRealName(), DesensitizedUtil.mobilePhone(tel), DesensitizedUtil.idCardNum(num, 4, 4), gson.toJson(myContactPeopleDTO))).execute();
                        myContactPeopleDTO.setContactTel(tel);
                        myContactPeopleDTO.setCardNum(num);
                    }
                    //保存投保信息
                    queryService.execute(() -> {
                        //保险订单信息
                        OrderInfo orderInfo = new OrderInfo();
                        orderInfo.setDestination(maingrouprecord.getTraveltitle() + "#" + maingrouprecord.getTraveldays() + "天");
                        orderInfo.setStartTime(DateUtil.format(new Date(maingrouprecord.getStartdate()), "yyyy-MM-dd HH:mm:ss"));
                        orderInfo.setEndTime(DateUtil.format(new Date(maingrouprecord.getStartdate() + maingrouprecord.getTraveldays() * DateUnit.DAY.getMillis() - 1), "yyyy-MM-dd 00:00:00"));
                        try {
                            orderInfo.setProductCode(insuranceFutrue.get().getThirdCode());
                        } catch (Exception e) {
                            e.printStackTrace();
                            return;
                        }
                        orderInfo.setSerialNumber("lt-" + orderId);
                        //投保人
                        PolicyHolderInfo policyHolderInfo = new PolicyHolderInfo();
                        BsUserLayoutUserInforDTO cuser = dslContext.selectFrom(BS_USERLAYOUT_USERINFOR).where(BS_USERLAYOUT_USERINFOR.ID.eq(model.getUserId())).limit(1).fetchOneInto(BsUserLayoutUserInforDTO.class);
                        policyHolderInfo.setSex(cuser.getSex().equals(Enum_UserSex.Male.getCode()) ? "1" : "0");
                        policyHolderInfo.setCardType(1);///身份证
                        policyHolderInfo.setCardNo(cuser.getIdCard());
                        String tmpidcard = IdcardUtil.isValidCard18(cuser.getIdCard()) ? cuser.getIdCard() : IdcardUtil.convert15To18(cuser.getIdCard());
                        String birth = DateUtil.format(new Date(DateUtil.parse(IdcardUtil.getBirthByIdCard(tmpidcard), "yyyyMMdd").getTime()), "yyyy-MM-dd");
                        policyHolderInfo.setBirthDay(birth);
                        try {
                            java.util.Map<String, Object> remark = gson.fromJson(cuser.getExtInfors(), new TypeToken<java.util.Map<String, Object>>() {
                            }.getType());
                            policyHolderInfo.setCName(remark.get("realName").toString());
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        //受保人列表
                        java.util.List<InsuredInfo> insuredInfos = new ArrayList<>();
                        for (BsMyContactPeopleDTO dto : myContactPeopleDTOs) {
                            /**
                             *
                             //，；，；，
                             IDCARD("IDCARD", "身份证"),
                             InnerPassport("InnerPassport", "通行证"),
                             CountryPassport("CountryPassport", "护照");
                             */
                            insuredInfos.add(new InsuredInfo(dto.getRealName(), switch (dto.getCardType()) {
                                case "IDCARD":
                                    yield 1;
                                case "CountryPassport":
                                    yield 4;
                                case "InnerPassport":
                                    yield 16;
                                default:
                                    yield 1;
                            }, dto.getCardNum(), dto.getBirthDay(), dto.getSex().equals(Enum_UserSex.Male.getCode()) ? "1" : "0"));
                        }

                        InsData insData = new InsData(orderInfo, policyHolderInfo, insuredInfos);
                        dslContext.insertInto(BsThirdinsurancelog.BS_THIRDINSURANCELOG).set(

                                new BsThirdinsurancelogRecord("" + YitIdHelper.nextId(), orderId, Enum_InsuranceType.WaitPay.getCode(), System.currentTimeMillis(), gson.toJson(insData))).execute();
                    });
                    //3，住房价
                    String roomId = "" + YitIdHelper.nextId();
                    dslContext.insertInto(BS_TRAVELGROUP_TOURORDERHOTELROOMRECORD).set(new BsTravelgroupTourorderhotelroomrecordRecord(roomId, model.getUserId(), orderId, model.getHotelRoomPriceId(), System.currentTimeMillis(), roomPrice)).execute();
                    //4，行程费用
                    String carPriceId = "" + YitIdHelper.nextId();
                    dslContext.insertInto(BS_TRAVELGROUP_TOURCARPRICERECORD).set(new BsTravelgroupTourcarpricerecordRecord(carPriceId, model.getUserId(), orderId, model.getPreTravelCarId(), System.currentTimeMillis(), maingrouprecord.getType().equals(Enum_TourTravelGroupType.Group.getCode()) ? new BigDecimal(groupStepPriceStr) : carPrice, maingrouprecord.getType().equals(Enum_TourTravelGroupType.Group.getCode()) ? new BigDecimal(groupStepPriceStr) : carPrice, gson.toJson(model.getCarExtInfor()))).execute();
                    //5，增值产品费用
                    if (!(model.getAddValueInfor() == null || model.getAddValueInfor().isEmpty())) {
                        if (!(addProductList == null || addProductList.isEmpty())) {
                            java.util.List<cn.roadtrip.mtravelbusinessmodule.sql.couple.travelgroup.tables.records.BsTravelgroupTourordershopproductrecordRecord> aplist = new ArrayList<>();
                            for (CoupleShopPdtDTO pdto : addProductList) {
                                aplist.add(new BsTravelgroupTourordershopproductrecordRecord("" + YitIdHelper.nextId(), Enum_TravelGroupTourOrderShopProductStats.WaitOff.getCode(), model.getUserId(), orderId, pdto.getId(), "0", System.currentTimeMillis(), pdto.getPrice(), 0l, gson.toJson(Map.of("dto", pdto, "num", model.getAddValueInfor().get(pdto.getId())))));
                            }
                            dslContext.batchInsert(aplist).execute();
                        }
                    }
                    totalPriceW = totalPrice;
                } finally {
                    lock.unlock();
                    //6，报名成功，锁定
                    _lockJoinTourTravelLine(maingrouprecord.getId(), model.getUserId(), DateUtil.formatDate(new Date(maingrouprecord.getStartdate())), maingrouprecord.getTraveldays());
                }

                DataBean rs = suc(Map.of("price", totalPriceW.toString(), "orderId", orderId,

                        "ticketPrice", ticketPriceStr, "carPrice", carPriceStr, "roomPrice", roomPriceStr, "insurancePrice", insurancePriceStr, "addPrice", addPriceStr, "groupStepPrice", groupStepPriceStr), 1, "suc", "操作成功");
                dslContext.commit();
                return rs;
            });
        } catch (Exception e) {
            e.printStackTrace();
            return err("trans-err", e.getMessage());
        }
    }


    /**
     * 计算费用
     *
     * @param model
     * @return
     */
    public DataBean calTourTravelPrice(Model_createTourTravelStep1 model) {
        BsTravelgroupMaintuortravellinerecordRecord maingrouprecord = _getPreTravelGroupById(model.getTravelGroupId());
        if (maingrouprecord == null) {
            return err("travelline-mainrecord-err", "主记录异常");
        }
        if (maingrouprecord.getStats().equals(Enum_MainTourTravelLineStats.Trash.getCode())) {
            return err("travelline-mainrecord-err", "主记录已删除");
        }
        //验证券
        CoupleUserDiscountCouponRecord ticket = null;
        if (model.getTicketId() != null) {
            //验证优惠券
            ticket = _checkTicket(model.getTicketId(), model.getUserId());
            if (ticket == null) {
                return err("ticket-err", "优惠券不存在");
            }
            if (ticket.getExpirationTime().toInstant(ZoneOffset.of("+8")).toEpochMilli() < System.currentTimeMillis()) {
                return err("ticket-overtime", "优惠券已过期");
            }
            if (!ticket.getUserId().equals(model.getUserId())) {
                return err("ticket-not-owner", "优惠券不属于你");
            }
        }
        CoupleUserDiscountCouponRecord finalticket = ticket;
        //计算总价
        String orderId = "" + YitIdHelper.nextId();
        try {
            return dslContext.transactionResult(ctx -> {
                BigDecimal totalPriceW = null;
                BigDecimal ticketPrice = null;
                BigDecimal groupStepPrice = null;
                BigDecimal carPrice = null;
                BigDecimal roomPrice = null;

                String ticketPriceStr = "0";//优惠券价格
                String groupStepPriceStr = "0";//阶梯价
                String carPriceStr = "0";//行程价
                String roomPriceStr = "0";//房价
                String insurancePriceStr = "0";//保险价
                String addPriceStr = "0";//增值服务价
                //上锁，避免报名人数超出
                RLock lock = redissonClient.getFairLock(TOUR_TRAVELLINE_ORDER_LOCK);
                try {
                    lock.tryLock(30, TimeUnit.SECONDS);
                    //验证报名人数
                    if (_canMarkTravelLineOrder(maingrouprecord.getMaxusernum(), model.getTravelGroupId())) {
                        return err("cant-mark", "报名人数已满，您已是候补");
                    }
                    //查询房价
                    Future<BsHotelRoomPriceDTO> roomFutrue = queryService.submit(new Callable<BsHotelRoomPriceDTO>() {
                        @Override
                        public BsHotelRoomPriceDTO call() throws Exception {
                            try {
                                BsHotelRoomPriceDTO hotelRoomPrices = dslContext.selectFrom(BS_HOTELROOMPRICE).where(BS_HOTELROOMPRICE.TRASH.eq(false).and(BS_HOTELROOMPRICE.DAYNUM.eq(maingrouprecord.getTraveldays())).and(BS_HOTELROOMPRICE.ID.eq(model.getHotelRoomPriceId()))).limit(1).fetchOneInto(BsHotelRoomPriceDTO.class);
                                return hotelRoomPrices;
                            } catch (Exception e) {
                                e.printStackTrace();
                                return null;
                            }
                        }
                    });
                    //查询车价
                    Future<BsPreTravelCarPriceDTO> carFutrue = queryService.submit(new Callable<BsPreTravelCarPriceDTO>() {
                        @Override
                        public BsPreTravelCarPriceDTO call() throws Exception {
                            String _carList = maingrouprecord.getPretravelcarlist();
                            java.util.List<String> carIdlist = new java.util.ArrayList<>();
                            try {
                                java.util.List<java.util.Map<String, Object>> carList = new Gson().fromJson(_carList, new TypeToken<java.util.List<java.util.Map<String, Object>>>() {
                                }.getType());
                                for (java.util.Map<String, Object> car : carList) {
                                    carIdlist.add(car.get("id").toString());
                                }
                            } catch (Exception e) {
                                java.util.List<String> carList = new Gson().fromJson(_carList, new TypeToken<java.util.List<String>>() {
                                }.getType());
                                carIdlist.addAll(carList);
                            }
                            try {
                                BsPreTravelCarPriceDTO preTravelCarPrices = dslContext.selectFrom(BS_PRETRAVELCARPRICE).where(BS_PRETRAVELCARPRICE.TRASH.eq(false).and(BS_PRETRAVELCARPRICE.DAYNUM.eq(maingrouprecord.getTraveldays())).and(BS_PRETRAVELCARPRICE.ID.in(carIdlist))).orderBy(BS_PRETRAVELCARPRICE.PRICE.desc()).limit(1).fetchOneInto(BsPreTravelCarPriceDTO.class);
                                return preTravelCarPrices;
                            } catch (Exception e) {
                                e.printStackTrace();
                                return null;
                            }

                        }
                    });
                    //查询保险价
                    Future<BsInsuranceDataDTO> insuranceFutrue = queryService.submit(new Callable<BsInsuranceDataDTO>() {
                        @Override
                        public BsInsuranceDataDTO call() throws Exception {
                            try {
                                BsInsuranceDataDTO insurancePrices = dslContext.selectFrom(BS_INSURANCEDATA).where(BS_INSURANCEDATA.TRASH.eq(false).and(BS_INSURANCEDATA.ID.eq(model.getInsuranceId())).and(BS_INSURANCEDATA.MINDAY.le(maingrouprecord.getTraveldays())).and(BS_INSURANCEDATA.MAXDAY.ge(maingrouprecord.getTraveldays()))).limit(1).fetchOneInto(BsInsuranceDataDTO.class);
                                return insurancePrices;
                            } catch (Exception e) {
                                e.printStackTrace();
                                return null;
                            }
                        }
                    });
                    //计算增值产品费用
                    Future<java.util.List<CoupleShopPdtDTO>> addPriceFuture = queryService.submit(new Callable<java.util.List<CoupleShopPdtDTO>>() {
                        @Override
                        public java.util.List<CoupleShopPdtDTO> call() throws Exception {
                            try {
                                java.util.List<CoupleShopPdtDTO> list = dslContext.selectFrom(COUPLE_SHOP_PDT).where(COUPLE_SHOP_PDT.ID.in(model.getAddValueInfor().keySet())).fetchInto(CoupleShopPdtDTO.class);
                                return list;
                            } catch (Exception e) {
                                e.printStackTrace();
                                return null;
                            }
                        }
                    });

                    //查询阶梯价
                    Future<BigDecimal> stepPriceFuture = queryService.submit(new Callable<BigDecimal>() {
                        @Override
                        public BigDecimal call() throws Exception {
                            String rs = dslContext.select(BS_TRAVELGROUP_TRAVELISTGROUP.STEPPRICE).from(BS_TRAVELGROUP_TRAVELISTGROUP).where(BS_TRAVELGROUP_TRAVELISTGROUP.ID.eq(DSL.select(BS_TRAVELGROUP_MAINTOURTRAVELRECORDBINDTRAVELLISTGROUP.TRAVELLISTGROUPID).from(BS_TRAVELGROUP_MAINTOURTRAVELRECORDBINDTRAVELLISTGROUP).where(BS_TRAVELGROUP_MAINTOURTRAVELRECORDBINDTRAVELLISTGROUP.MAINTOURTRAVELRECORDID.eq(maingrouprecord.getId())).limit(1))).limit(1).fetchOneInto(String.class);
                            Gson gson = new Gson();
                            try {
                                java.util.List<_STEP_PRICE_MODEL_> list = gson.fromJson(rs, new com.google.gson.reflect.TypeToken<java.util.List<_STEP_PRICE_MODEL_>>() {
                                }.getType());
                                for (_STEP_PRICE_MODEL_ m : list) {
                                    if (m.getMinNum() <= model.getContactPeopleIds().size() && model.getContactPeopleIds().size() <= m.getMaxNum()) {
                                        return new BigDecimal(m.getPrice());
                                    }
                                }
                                return null;
                            } catch (Exception e) {
                                return null;
                            }
                        }
                    });


                    BigDecimal totalPrice = new BigDecimal(0);
                    ticketPrice = finalticket == null ? new BigDecimal(0) : finalticket.getPrice();
                    if (maingrouprecord.getType().equals(Enum_TourTravelGroupType.Group.getCode())) {
                        try {
                            groupStepPrice = stepPriceFuture.get();
                        } catch (Exception e) {
                            e.printStackTrace();
                            return err("step-price-err", "阶梯价异常");
                        }
                    }
                    try {
                        carPrice = roomFutrue.get().getPrice();
                    } catch (Exception e) {
                        e.printStackTrace();
                        return err("car-price-err", "出行价异常");
                    }
                    try {
                        roomPrice = carFutrue.get().getPrice();
                    } catch (Exception e) {
                        e.printStackTrace();
                        return err("room-price-err", "住宿价异常");
                    }


                    java.util.List<CoupleShopPdtDTO> addProductList = addPriceFuture == null ? new ArrayList<>() : addPriceFuture.get();
                    {
                        //计算用券
                        if (model.getTicketId() != null) {
                            totalPrice = totalPrice.subtract(ticketPrice);
                            ticketPriceStr = ticketPrice.toString();
                        }
                        //计算车费
                        if (maingrouprecord.getType().equals(Enum_TourTravelGroupType.Self.getCode())) {
                            //小团费用
                            totalPrice = totalPrice.add(carPrice.multiply(new BigDecimal(model.getContactPeopleIds().size())));
                            carPriceStr = carPrice.multiply(new BigDecimal(model.getContactPeopleIds().size())).toString();
                        } else {
                            //大团费用
                            totalPrice = totalPrice.add(groupStepPrice.multiply(new BigDecimal(model.getContactPeopleIds().size())));
                            groupStepPriceStr = groupStepPrice.multiply(new BigDecimal(model.getContactPeopleIds().size())).toString();
                        }
                        //计算房间费
                        totalPrice = totalPrice.add(roomPrice.multiply(new BigDecimal(model.getContactPeopleIds().size())));
                        roomPriceStr = roomPrice.multiply(new BigDecimal(model.getContactPeopleIds().size())).toString();
                        //计算增值产品价格
                        BigDecimal tmpAddPrice = new BigDecimal(0);
                        if (!(model.getAddValueInfor() == null || model.getAddValueInfor().isEmpty())) {
                            java.util.List<CoupleShopPdtDTO> addPriceLIst = addProductList;
                            if (!(addPriceLIst == null || addPriceLIst.isEmpty())) {
                                for (CoupleShopPdtDTO dto : addPriceLIst) {
                                    totalPrice = totalPrice.add(dto.getPrice().multiply(new BigDecimal(model.getAddValueInfor().get(dto.getId()))));//给的原价
                                    tmpAddPrice = tmpAddPrice.add(dto.getPrice().multiply(new BigDecimal(model.getAddValueInfor().get(dto.getId()))));
                                }
                            }
                        }
                        addPriceStr = tmpAddPrice.toString();
                        //计算保险
                        totalPrice = totalPrice.add(insuranceFutrue.get().getPerPrice().multiply(new BigDecimal(model.getContactPeopleIds().size())));
                        insurancePriceStr = insuranceFutrue.get().getPerPrice().multiply(new BigDecimal(model.getContactPeopleIds().size())).toString();
                    }
                    Gson gson = new Gson();
                    //生成订单

                    //报名信息
                    java.util.List<BsMyContactPeopleDTO> myContactPeopleDTOs = dslContext.selectFrom(BS_MYCONTACTPEOPLE).where(BS_MYCONTACTPEOPLE.TRASH.eq(false)).and(BS_MYCONTACTPEOPLE.GROUPUSERID.eq(model.getUserId())).and(BS_MYCONTACTPEOPLE.ID.in(model.getContactPeopleIds())).fetchInto(BsMyContactPeopleDTO.class);
                    if (myContactPeopleDTOs == null) {
                        throw new Exception("报名人信息异常");
                    }

                    totalPriceW = totalPrice;
                } finally {
                    lock.unlock();
                }

                DataBean rs = suc(Map.of("price", totalPriceW.toString(), "orderId", orderId,

                        "ticketPrice", ticketPriceStr, "carPrice", carPriceStr, "roomPrice", roomPriceStr, "insurancePrice", insurancePriceStr, "addPrice", addPriceStr, "groupStepPrice", groupStepPriceStr), 1, "suc", "操作成功");
                dslContext.commit();
                return rs;
            });
        } catch (Exception e) {
            e.printStackTrace();
            return err("trans-err", e.getMessage());
        }
    }


    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    @EqualsAndHashCode
    public static class Model_getMarkTourUserList {
        private String travelGroupId;
    }

    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    @EqualsAndHashCode
    public static class VPO_getMarkTourUserList {
        private java.lang.String realName;

        public java.lang.String getRealName() {
            return this.realName;
        }

        private java.lang.String sex;

        public java.lang.String getSex() {
            return this.sex;
        }

        private java.lang.String phone;

        public java.lang.String getPhone() {
            return this.phone;
        }

        private java.lang.String stats;

        public java.lang.String getStats() {
            return this.stats;
        }

        private java.lang.String nickName;

        public java.lang.String getNickName() {
            return this.nickName;
        }

        private java.lang.String cover;

        public java.lang.String getCover() {
            return this.cover;
        }
    }

    /**
     * 团报名人列表
     *
     * @param model
     * @return
     */
    public DataBean getMarkTourUserList(Model_getMarkTourUserList model) {
        try {
            return dslContext.transactionResult(ctx -> {
                //todo
                java.util.List<VPO_getMarkTourUserList> list = dslContext.resultQuery("SELECT\n" + "t.realName,\n" + "t.sex,\n" + "t.phone,\n" + "BS_TravelGroup_TourOrderRecord.stats,\n" + "IFNULL(BS_UserLayout_UserInfor.nickName,'nil') as nickName,\n" + "IFNULL(BS_UserLayout_UserInfor.cover,'nil') as cover\n" + "FROM(\n" + "SELECT\n" + "BS_TravelGroup_TourUserInfor.tourOrderRecordId,\n" + "BS_TravelGroup_TourUserInfor.realName,\n" + "BS_TravelGroup_TourUserInfor.sex,\n" + "BS_TravelGroup_TourUserInfor.phone\n" + "FROM\n" + "BS_TravelGroup_TourUserInfor,\n" + "BS_TravelGroup_TourOrderRecord\n" + "WHERE\n" + "BS_TravelGroup_TourOrderRecord.travelGroupId = ?\n" + "and  BS_TravelGroup_TourUserInfor.tourOrderRecordId =BS_TravelGroup_TourOrderRecord.id\n" + ") as t\n" + "LEFT JOIN BS_UserLayout_UserInfor on BS_UserLayout_UserInfor.phone = t.phone\n" + "LEFT JOIN BS_TravelGroup_TourOrderRecord on t.tourOrderRecordId = BS_TravelGroup_TourOrderRecord.id", model.getTravelGroupId()).fetchInto(VPO_getMarkTourUserList.class);
                dslContext.commit();
                if (list == null || list.isEmpty()) {
                    return DataBean.sucEmpty();
                }
                return suc(list, list.size(), "suc", "操作成功");
            });
        } catch (Exception e) {
            e.printStackTrace();
            return err("trans-err", e.getMessage());
        }
    }

    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    @EqualsAndHashCode
    public static class Model_getTourPlayGroupList {

        private String userId;
        /**
         * 订单状态
         * Waitpay("Waitpay", "已报名，待付款"),
         * Mark("Mark", "已报名候选"),
         * MarkPayed("MarkPayed", "候选已付款"),
         * Payed("Payed", "已付款"),
         * Join("Join", "付款成功，已入团"),
         * <p>
         * Payback("Payback", "已退款"),
         * Out("Out", "已离开"),
         * Timeout("Timeout", "超时退出"),
         * Finished("Finished", "已完成，不可更改"),
         * PayFail("PayFail", "付款失败"),
         * Dispatched("Dispatched", "已被调度");
         */
        private java.util.List<String> orderStats;//可选
    }

    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    @EqualsAndHashCode
    public static class VPO_getTourPlayGroupList {
        private String userId;
        private java.lang.String tourOrderId;

        private java.lang.String orderStats;

        private java.lang.Long payExpireTime;

        private java.lang.Long orderCreateTime;

        private java.math.BigDecimal finalPrice;
        private String startPoint;

        private String travelGroupType;

        private java.lang.String travelGroupId;

        private java.lang.String groupStats;

        private java.lang.String dispatchStats;

        private java.lang.Long startDate;

        private java.lang.Integer travelDays;

        private java.lang.String strartFromCityTitle;

        private java.lang.String startFromCityId;

        private java.lang.String travelListGroupId;
        private String travelLineExtInfor;
        private Integer reportNum;
    }

    /**
     * 查询游客报的团列表
     *
     * @param model
     * @return
     */
    public DataBean getTourPlayGroupList(Model_getTourPlayGroupList model) {
        try {
            return dslContext.transactionResult(ctx -> {
                //todo
                java.util.List<VPO_getTourPlayGroupList> list = dslContext.resultQuery("SELECT\n" +
                                "BS_TravelGroup_TourOrderRecord.userId,\n" +
                                "BS_TravelGroup_TourOrderRecord.id as tourOrderId,\n" +
                                "BS_TravelGroup_TourOrderRecord.stats as orderStats,\n" +
                                "BS_TravelGroup_TourOrderRecord.payExpireTime,\n" +
                                "BS_TravelGroup_TourOrderRecord.createTime as orderCreateTime,\n" +
                                "BS_TravelGroup_TourOrderRecord.finalPrice,\n" +
                                "BS_TravelGroup_TourOrderRecord.startPoint,\n" +
                                "BS_TravelGroup_MainTuorTravelLineRecord.type as travelGroupType,\n" +
                                "BS_TravelGroup_MainTuorTravelLineRecord.id as travelGroupId,\n" +
                                "BS_TravelGroup_MainTuorTravelLineRecord.stats as groupStats,\n" +
                                "BS_TravelGroup_MainTuorTravelLineRecord.dispatchStats as dispatchStats,\n" +
                                "BS_TravelGroup_MainTuorTravelLineRecord.startDate,\n" +
                                "BS_TravelGroup_MainTuorTravelLineRecord.travelDays,\n" +
                                "BS_TravelGroup_MainTuorTravelLineRecord.strartFromCityTitle,\n" +
                                "BS_TravelGroup_MainTuorTravelLineRecord.startFromCityId,\n" +
                                "BS_TravelGroup_MainTourTravelRecordBindTravelListGroup.travelListGroupId as travelListGroupId\n" +
                                "FROM\n" +
                                "(\n" +
                                "SELECT\n" +
                                "BS_TravelGroup_TourOrderRecord.id\n" +
                                "FROM\n" +
                                "BS_TravelGroup_TourOrderRecord\n" +
                                "WHERE\n" +
                                "BS_TravelGroup_TourOrderRecord.userId = ?\n" +
                                ") as tor\n" +
                                "LEFT JOIN\n" +
                                "BS_TravelGroup_TourOrderRecord on BS_TravelGroup_TourOrderRecord.id = tor.id\n" +
                                "LEFT JOIN\n" +
                                "BS_TravelGroup_MainTuorTravelLineRecord on\n" +
                                "BS_TravelGroup_MainTuorTravelLineRecord.id = BS_TravelGroup_TourOrderRecord.travelGroupId\n" +
                                "LEFT JOIN BS_TravelGroup_MainTourTravelRecordBindTravelListGroup on \n" +
                                "BS_TravelGroup_MainTourTravelRecordBindTravelListGroup.mainTourTravelRecordId = BS_TravelGroup_MainTuorTravelLineRecord.id\n" +
                                "\n" +
                                "order by BS_TravelGroup_TourOrderRecord.createTime desc",
                        model.getUserId()
                ).fetchInto(VPO_getTourPlayGroupList.class);
                if (list == null || list.isEmpty()) {
                    return DataBean.sucEmpty();
                }
                if (!(model.getOrderStats() == null || model.getOrderStats().isEmpty())) {
                    list = list.stream().filter(o -> {
                        return model.getOrderStats().contains(o.getOrderStats());
                    }).collect(Collectors.toList());
                }
                dslContext.commit();
                return suc(list, list.size(), "suc", "操作成功");
            });
        } catch (Exception e) {
            e.printStackTrace();
            return err("trans-err", e.getMessage());
        }
    }


    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    @EqualsAndHashCode
    public static class Model_getUserAllOrder {
        String userId;
    }

    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    @EqualsAndHashCode
    public static class VPO_getUserAllOrder {
        private String type;
        private Object data;
    }

    /**
     * 所有商品列表对象
     */
    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    @EqualsAndHashCode
    public static class _getUserAllOrder_PTDS_ {
        private java.lang.String pdtorderid;
        private java.lang.Long creatTime;

        private java.lang.String pdtId;

        private java.math.BigDecimal price;

        private java.lang.String title;

        private java.lang.String extinfors;

        private java.lang.String cover;
    }

    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    @EqualsAndHashCode
    public static class _getUserAllOrder_AllOrderId_ {
        private java.lang.String id;

        public java.lang.String getId() {
            return this.id;
        }

        private java.lang.Long creatTime;

        public java.lang.Long getCreatTime() {
            return this.creatTime;
        }

        private java.lang.String type;

        public java.lang.String getType() {
            return this.type;
        }
    }

    /**
     * 行程报名人数
     */
    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    @EqualsAndHashCode
    public static class _getUserAllOrder_ReportNum {
        private String travelId;
        private Integer num;
    }


    /**
     * 查询用户所有得订单
     *
     * @param model
     * @return
     */
    public DataBean getUserAllOrder(
            Model_getUserAllOrder model
    ) {
        try {
            return dslContext.transactionResult(ctx -> {
                //todo
//查询用户所有订单
                java.util.List<_getUserAllOrder_AllOrderId_> allOrderIdList = new ArrayList<>();
                try {
                    allOrderIdList = dslContext.resultQuery("SELECT\n" +
                                            "couple_shop_order.id,\n" +
                                            "UNIX_TIMESTAMP(couple_shop_order.create_time)*1000 as creatTime,\n" +
                                            "\"ptd\" as type\n" +
                                            "FROM\n" +
                                            "couple_shop_order\n" +
                                            "WHERE\n" +
                                            "couple_shop_order.user_id = ?\n" +
                                            "\n" +
                                            "UNION\n" +
                                            "SELECT\n" +
                                            "BS_TravelGroup_TourOrderRecord.id,\n" +
                                            "BS_TravelGroup_TourOrderRecord.createTime,\n" +
                                            "\"travel\" as type\n" +
                                            "FROM\n" +
                                            "BS_TravelGroup_TourOrderRecord\n" +
                                            "WHERE\n" +
                                            "BS_TravelGroup_TourOrderRecord.userId = ?"
                                    , model.getUserId(),
                                    model.getUserId()
                            )
                            .fetchInto(_getUserAllOrder_AllOrderId_.class)
                            .stream()
                            .sorted(Comparator.comparing(_getUserAllOrder_AllOrderId_::getCreatTime).reversed())
                            .collect(Collectors.toList());
                } catch (Exception e) {
                    e.printStackTrace();
                    return DataBean.sucEmpty();
                }
                //行程报名人数
                java.util.List<String> travelOrderIds = new ArrayList<>();
                for (_getUserAllOrder_AllOrderId_ o : allOrderIdList) {
                    if (o.getType().equals("travel")) {
                        travelOrderIds.add(o.getId());
                    }
                }
                java.util.Map<String, Integer> reportNum = new HashMap<>();
                if (!(travelOrderIds == null || travelOrderIds.isEmpty())) {
                    try {
                        reportNum = dslContext.select(
                                BS_TRAVELGROUP_TOURORDERRECORD.TRAVELGROUPID.as("travelId"),
                                DSL.count(BS_TRAVELGROUP_TOURORDERRECORD.TRAVELGROUPID).as("num")
                        ).from(
                                BS_TRAVELGROUP_TOURORDERRECORD
                        ).where(
                                BS_TRAVELGROUP_TOURORDERRECORD.ID.in(travelOrderIds)
                        ).and(
                                BS_TRAVELGROUP_TOURORDERRECORD.STATS.in(
                                        Enum_TravelGroupTourOrderStats.Join.getCode(),
                                        Enum_TravelGroupTourOrderStats.Waitpay.getCode(),
                                        Enum_TravelGroupTourOrderStats.Payed.getCode()
                                )
                        ).groupBy(
                                BS_TRAVELGROUP_TOURORDERRECORD.TRAVELGROUPID
                        ).fetchInto(_getUserAllOrder_ReportNum.class).stream().collect(Collectors.toMap(_getUserAllOrder_ReportNum::getTravelId, _getUserAllOrder_ReportNum::getNum));
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }


                //行程订单
                Future<java.util.Map<String, VPO_getTourPlayGroupList>> travelOrderMap = queryService.submit(new Callable<java.util.Map<String, VPO_getTourPlayGroupList>>() {
                    @Override
                    public java.util.Map<String, VPO_getTourPlayGroupList> call() throws Exception {
                        //todo
                        try {
                            java.util.List<VPO_getTourPlayGroupList> list = dslContext.resultQuery("SELECT\n" +
                                            "BS_TravelGroup_TourOrderRecord.userId,\n" +
                                            "BS_TravelGroup_TourOrderRecord.id as tourOrderId,\n" +
                                            "BS_TravelGroup_TourOrderRecord.stats as orderStats,\n" +
                                            "BS_TravelGroup_TourOrderRecord.payExpireTime,\n" +
                                            "BS_TravelGroup_TourOrderRecord.createTime as orderCreateTime,\n" +
                                            "BS_TravelGroup_TourOrderRecord.finalPrice,\n" +
                                            "BS_TravelGroup_TourOrderRecord.startPoint,\n" +
                                            "BS_TravelGroup_MainTuorTravelLineRecord.type as travelGroupType,\n" +
                                            "BS_TravelGroup_MainTuorTravelLineRecord.id as travelGroupId,\n" +
                                            "BS_TravelGroup_MainTuorTravelLineRecord.stats as groupStats,\n" +
                                            "BS_TravelGroup_MainTuorTravelLineRecord.dispatchStats as dispatchStats,\n" +
                                            "BS_TravelGroup_MainTuorTravelLineRecord.startDate,\n" +
                                            "BS_TravelGroup_MainTuorTravelLineRecord.travelDays,\n" +
                                            "BS_TravelGroup_MainTuorTravelLineRecord.strartFromCityTitle,\n" +
                                            "BS_TravelGroup_MainTuorTravelLineRecord.startFromCityId,\n" +
                                            "BS_TravelGroup_MainTuorTravelLineRecord.extInfor as travelLineExtInfor,\n" +
                                            "BS_TravelGroup_MainTourTravelRecordBindTravelListGroup.travelListGroupId as travelListGroupId\n" +
                                            "FROM\n" +
                                            "(\n" +
                                            "SELECT\n" +
                                            "BS_TravelGroup_TourOrderRecord.id\n" +
                                            "FROM\n" +
                                            "BS_TravelGroup_TourOrderRecord\n" +
                                            "WHERE\n" +
                                            "BS_TravelGroup_TourOrderRecord.userId = ?\n" +
                                            ") as tor\n" +
                                            "LEFT JOIN\n" +
                                            "BS_TravelGroup_TourOrderRecord on BS_TravelGroup_TourOrderRecord.id = tor.id\n" +
                                            "LEFT JOIN\n" +
                                            "BS_TravelGroup_MainTuorTravelLineRecord on\n" +
                                            "BS_TravelGroup_MainTuorTravelLineRecord.id = BS_TravelGroup_TourOrderRecord.travelGroupId\n" +
                                            "LEFT JOIN BS_TravelGroup_MainTourTravelRecordBindTravelListGroup on \n" +
                                            "BS_TravelGroup_MainTourTravelRecordBindTravelListGroup.mainTourTravelRecordId = BS_TravelGroup_MainTuorTravelLineRecord.id\n" +
                                            "\n" +
                                            "order by BS_TravelGroup_TourOrderRecord.createTime desc",
                                    model.getUserId()
                            ).fetchInto(VPO_getTourPlayGroupList.class);
                            return list.stream().collect(Collectors.toMap(k -> k.getTourOrderId(), v -> v));
                        } catch (Exception e) {
                            e.printStackTrace();
                            return new java.util.HashMap<>();
                        }

                    }
                });
                //查找购买商品订单
                Future<java.util.Map<String, _getUserAllOrder_PTDS_>> ptdOrderMap = queryService.submit(new Callable<java.util.Map<String, _getUserAllOrder_PTDS_>>() {
                    @Override
                    public java.util.Map<String, _getUserAllOrder_PTDS_> call() throws Exception {
                        //todo
                        try {
                            java.util.List<_getUserAllOrder_PTDS_> list = dslContext.resultQuery("\n" +
                                            "SELECT\n" +
                                            "couple_shop_order.id as pdtorderid,\n" +
                                            "UNIX_TIMESTAMP(couple_shop_order.create_time)*1000 as creatTime,\n" +
                                            "couple_shop_order.pdt_id,\n" +
                                            "couple_shop_order.price,\n" +
                                            "couple_shop_pdt.title,\n" +
                                            "couple_shop_pdt.extinfors,\n" +
                                            "couple_shop_pdt.cover\n" +
                                            "FROM\n" +
                                            "couple_shop_order,\n" +
                                            "couple_shop_pdt\n" +
                                            "WHERE\n" +
                                            "couple_shop_order.user_id = ?\n" +
                                            "and couple_shop_pdt.id = couple_shop_order.pdt_id"
                                    , model.getUserId()
                            ).fetchInto(_getUserAllOrder_PTDS_.class);
                            return list.stream().collect(Collectors.toMap(k -> k.getPdtId(), v -> v));
                        } catch (Exception e) {
                            e.printStackTrace();
                            return new java.util.HashMap<>();
                        }
                    }
                });
                java.util.Map<String, VPO_getTourPlayGroupList> tmap = travelOrderMap.get();
                java.util.Map<String, _getUserAllOrder_PTDS_> pmap = ptdOrderMap.get();
                java.util.List<VPO_getUserAllOrder> rslist = new ArrayList<>();
                for (_getUserAllOrder_AllOrderId_ order : allOrderIdList) {
                    if (order.getType().equals("travel")) {
                        VPO_getTourPlayGroupList pg = tmap.get(order.getId());
                        pg.setReportNum(reportNum.get(pg.getTravelGroupId()) == null ? 0 : reportNum.get(pg.getTravelGroupId()));
                        rslist.add(new VPO_getUserAllOrder(
                                "travel",
                                pg
                        ));
                    } else {
                        rslist.add(new VPO_getUserAllOrder(
                                "ptd",
                                pmap.get(order.getId())
                        ));

                    }
                }

                dslContext.commit();
                return suc(rslist, rslist.size(), "suc", "操作成功");
            });
        } catch (Exception e) {
            e.printStackTrace();
            return err("trans-err", e.getMessage());
        }
    }
}

